Merge m-c to inbound, a=merge

MozReview-Commit-ID: AzYu7EXTIlg
This commit is contained in:
Wes Kocher 2017-03-14 17:23:26 -07:00
commit 0902d5e08e
315 changed files with 21684 additions and 20011 deletions

View File

@ -61,7 +61,9 @@ browser/base/content/test/general/file_csp_block_all_mixedcontent.html
browser/base/content/test/urlbar/file_blank_but_not_blank.html browser/base/content/test/urlbar/file_blank_but_not_blank.html
browser/base/content/newtab/** browser/base/content/newtab/**
browser/components/downloads/** browser/components/downloads/**
browser/components/sessionstore/** # Test files that are really json not js, and don't need to be linted.
browser/components/sessionstore/test/unit/data/sessionstore_valid.js
browser/components/sessionstore/test/unit/data/sessionstore_invalid.js
browser/components/tabview/** browser/components/tabview/**
# generated & special files in cld2 # generated & special files in cld2
browser/components/translation/cld2/** browser/components/translation/cld2/**

View File

@ -4,16 +4,6 @@
'use strict' 'use strict'
const { Cc, Ci, Cu } = require('chrome'); const { Cc, Ci, Cu } = require('chrome');
const bmsrv = Cc['@mozilla.org/browser/nav-bookmarks-service;1'].
getService(Ci.nsINavBookmarksService);
const hsrv = Cc['@mozilla.org/browser/nav-history-service;1'].
getService(Ci.nsINavHistoryService);
const brsrv = Cc["@mozilla.org/browser/nav-history-service;1"]
.getService(Ci.nsIBrowserHistory);
const tagsrv = Cc['@mozilla.org/browser/tagging-service;1'].
getService(Ci.nsITaggingService);
const asyncHistory = Cc['@mozilla.org/browser/history;1'].
getService(Ci.mozIAsyncHistory);
const { send } = require('sdk/addon/events'); const { send } = require('sdk/addon/events');
const { setTimeout } = require('sdk/timers'); const { setTimeout } = require('sdk/timers');
const { newURI } = require('sdk/url/utils'); const { newURI } = require('sdk/url/utils');
@ -41,7 +31,7 @@ exports.invalidResolve = invalidResolve;
// Removes all children of group // Removes all children of group
function clearBookmarks (group) { function clearBookmarks (group) {
group group
? bmsrv.removeFolderChildren(group.id) ? PlacesUtils.bookmarks.removeFolderChildren(group.id)
: clearAllBookmarks(); : clearAllBookmarks();
} }
@ -65,12 +55,15 @@ exports.resetPlaces = resetPlaces;
function compareWithHost (assert, item) { function compareWithHost (assert, item) {
let id = item.id; let id = item.id;
let type = item.type === 'group' ? bmsrv.TYPE_FOLDER : bmsrv['TYPE_' + item.type.toUpperCase()]; let type = item.type === 'group' ?
PlacesUtils.bookmarks.TYPE_FOLDER :
PlacesUtils.bookmarks['TYPE_' + item.type.toUpperCase()];
let url = item.url && !item.url.endsWith('/') ? item.url + '/' : item.url; let url = item.url && !item.url.endsWith('/') ? item.url + '/' : item.url;
if (type === bmsrv.TYPE_BOOKMARK) { if (type === PlacesUtils.bookmarks.TYPE_BOOKMARK) {
assert.equal(url, bmsrv.getBookmarkURI(id).spec.toString(), 'Matches host url'); assert.equal(url, PlacesUtils.bookmarks.getBookmarkURI(id).spec.toString(),
let tags = tagsrv.getTagsForURI(newURI(item.url)); 'Matches host url');
let tags = PlacesUtils.tagging.getTagsForURI(newURI(item.url));
for (let tag of tags) { for (let tag of tags) {
// Handle both array for raw data and set for instances // Handle both array for raw data and set for instances
if (Array.isArray(item.tags)) if (Array.isArray(item.tags))
@ -82,45 +75,45 @@ function compareWithHost (assert, item) {
Array.isArray(item.tags) ? item.tags.length : item.tags.size, Array.isArray(item.tags) ? item.tags.length : item.tags.size,
'matches tag count'); 'matches tag count');
} }
if (type !== bmsrv.TYPE_SEPARATOR) { if (type !== PlacesUtils.bookmarks.TYPE_SEPARATOR) {
assert.equal(item.title, bmsrv.getItemTitle(id), 'Matches host title'); assert.equal(item.title, PlacesUtils.bookmarks.getItemTitle(id),
'Matches host title');
} }
assert.equal(item.index, bmsrv.getItemIndex(id), 'Matches host index'); assert.equal(item.index, PlacesUtils.bookmarks.getItemIndex(id),
assert.equal(item.group.id || item.group, bmsrv.getFolderIdForItem(id), 'Matches host group id'); 'Matches host index');
assert.equal(type, bmsrv.getItemType(id), 'Matches host type'); assert.equal(item.group.id || item.group,
PlacesUtils.bookmarks.getFolderIdForItem(id),
'Matches host group id');
assert.equal(type, PlacesUtils.bookmarks.getItemType(id),
'Matches host type');
} }
exports.compareWithHost = compareWithHost; exports.compareWithHost = compareWithHost;
/**
* Adds visits to places.
*
* @param {Array|String} urls Either an array of urls to add, or a single url
* as a string.
*/
function addVisits (urls) { function addVisits (urls) {
var deferred = defer(); return PlacesUtils.history.insertMany([].concat(urls).map(createVisit));
asyncHistory.updatePlaces([].concat(urls).map(createVisit), {
handleResult: function () {},
handleError: deferred.reject,
handleCompletion: deferred.resolve
});
return deferred.promise;
} }
exports.addVisits = addVisits; exports.addVisits = addVisits;
function removeVisits (urls) { function removeVisits (urls) {
[].concat(urls).map(url => { PlacesUtils.history.remove(urls);
hsrv.removePage(newURI(url));
});
} }
exports.removeVisits = removeVisits; exports.removeVisits = removeVisits;
// Creates a mozIVisitInfo object // Creates a mozIVisitInfo object
function createVisit (url) { function createVisit (url) {
let place = {} return {
place.uri = newURI(url); url,
place.title = "Test visit for " + place.uri.spec; title: "Test visit for " + url,
place.visits = [{ visits: [{
transitionType: hsrv.TRANSITION_LINK, transition: PlacesUtils.history.TRANSITION_LINK
visitDate: +(new Date()) * 1000, }]
referredURI: undefined };
}];
return place;
} }
function createBookmark (data) { function createBookmark (data) {
@ -141,7 +134,7 @@ function createBookmark (data) {
exports.createBookmark = createBookmark; exports.createBookmark = createBookmark;
function historyBatch () { function historyBatch () {
hsrv.runInBatchMode(() => {}, null); PlacesUtils.history.runInBatchMode(() => {}, null);
} }
exports.historyBatch = historyBatch; exports.historyBatch = historyBatch;

View File

@ -36,9 +36,9 @@ exports.testEmptyQuery = function*(assert) {
'matches url'); 'matches url');
assert.equal(results[1].url, 'http://simplequery-2.com/', assert.equal(results[1].url, 'http://simplequery-2.com/',
'matches url'); 'matches url');
assert.equal(results[0].title, 'Test visit for ' + results[0].url, assert.equal(results[0].title, 'Test visit for ' + 'http://simplequery-1.com',
'title matches'); 'title matches');
assert.equal(results[1].title, 'Test visit for ' + results[1].url, assert.equal(results[1].title, 'Test visit for ' + 'http://simplequery-2.com',
'title matches'); 'title matches');
assert.equal(results[0].visitCount, 1, 'matches access'); assert.equal(results[0].visitCount, 1, 'matches access');
assert.equal(results[1].visitCount, 1, 'matches access'); assert.equal(results[1].visitCount, 1, 'matches access');

View File

@ -6665,6 +6665,10 @@
// Set the cursor to an arrow during tab drags. // Set the cursor to an arrow during tab drags.
dt.mozCursor = "default"; dt.mozCursor = "default";
// Set the tab as the source of the drag, which ensures we have a stable
// node to deliver the `dragend` event. See bug 1345473.
dt.addElement(tab);
// Create a canvas to which we capture the current tab. // Create a canvas to which we capture the current tab.
// Until canvas is HiDPI-aware (bug 780362), we need to scale the desired // Until canvas is HiDPI-aware (bug 780362), we need to scale the desired
// canvas size (in CSS pixels) to the window's backing resolution in order // canvas size (in CSS pixels) to the window's backing resolution in order

View File

@ -0,0 +1,31 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ExtensionPreferencesManager",
"resource://gre/modules/ExtensionPreferencesManager.jsm");
/* eslint-disable mozilla/balanced-listeners */
extensions.on("manifest_chrome_settings_overrides", (type, directive, extension, manifest) => {
if (manifest.chrome_settings_overrides.homepage) {
ExtensionPreferencesManager.setSetting(extension, "homepage_override",
manifest.chrome_settings_overrides.homepage);
}
});
/* eslint-enable mozilla/balanced-listeners */
ExtensionPreferencesManager.addSetting("homepage_override", {
prefNames: [
"browser.startup.homepage",
],
setCallback(value) {
return {
"browser.startup.homepage": value,
};
},
});

View File

@ -2,6 +2,7 @@
category webextension-scripts bookmarks chrome://browser/content/ext-bookmarks.js category webextension-scripts bookmarks chrome://browser/content/ext-bookmarks.js
category webextension-scripts browserAction chrome://browser/content/ext-browserAction.js category webextension-scripts browserAction chrome://browser/content/ext-browserAction.js
category webextension-scripts browsingData chrome://browser/content/ext-browsingData.js category webextension-scripts browsingData chrome://browser/content/ext-browsingData.js
category webextension-scripts chrome-settings-overrides chrome://browser/content/ext-chrome-settings-overrides.js
category webextension-scripts commands chrome://browser/content/ext-commands.js category webextension-scripts commands chrome://browser/content/ext-commands.js
category webextension-scripts contextMenus chrome://browser/content/ext-contextMenus.js category webextension-scripts contextMenus chrome://browser/content/ext-contextMenus.js
category webextension-scripts desktop-runtime chrome://browser/content/ext-desktop-runtime.js category webextension-scripts desktop-runtime chrome://browser/content/ext-desktop-runtime.js
@ -32,6 +33,7 @@ category webextension-scripts-addon tabs chrome://browser/content/ext-c-tabs.js
category webextension-schemas bookmarks chrome://browser/content/schemas/bookmarks.json category webextension-schemas bookmarks chrome://browser/content/schemas/bookmarks.json
category webextension-schemas browser_action chrome://browser/content/schemas/browser_action.json category webextension-schemas browser_action chrome://browser/content/schemas/browser_action.json
category webextension-schemas browsing_data chrome://browser/content/schemas/browsing_data.json category webextension-schemas browsing_data chrome://browser/content/schemas/browsing_data.json
category webextension-schemas chrome_settings_overrides chrome://browser/content/schemas/chrome_settings_overrides.json
category webextension-schemas commands chrome://browser/content/schemas/commands.json category webextension-schemas commands chrome://browser/content/schemas/commands.json
category webextension-schemas context_menus chrome://browser/content/schemas/context_menus.json category webextension-schemas context_menus chrome://browser/content/schemas/context_menus.json
category webextension-schemas context_menus_internal chrome://browser/content/schemas/context_menus_internal.json category webextension-schemas context_menus_internal chrome://browser/content/schemas/context_menus_internal.json

View File

@ -15,6 +15,7 @@ browser.jar:
content/browser/ext-bookmarks.js content/browser/ext-bookmarks.js
content/browser/ext-browserAction.js content/browser/ext-browserAction.js
content/browser/ext-browsingData.js content/browser/ext-browsingData.js
content/browser/ext-chrome-settings-overrides.js
content/browser/ext-commands.js content/browser/ext-commands.js
content/browser/ext-contextMenus.js content/browser/ext-contextMenus.js
content/browser/ext-desktop-runtime.js content/browser/ext-desktop-runtime.js

View File

@ -0,0 +1,25 @@
[
{
"namespace": "manifest",
"types": [
{
"$extend": "WebExtensionManifest",
"properties": {
"chrome_settings_overrides": {
"type": "object",
"optional": true,
"additionalProperties": { "$ref": "UnrecognizedProperty" },
"properties": {
"homepage": {
"type": "string",
"format": "url",
"optional": true,
"preprocess": "localize"
}
}
}
}
}
]
}
]

View File

@ -6,6 +6,7 @@ browser.jar:
content/browser/schemas/bookmarks.json content/browser/schemas/bookmarks.json
content/browser/schemas/browser_action.json content/browser/schemas/browser_action.json
content/browser/schemas/browsing_data.json content/browser/schemas/browsing_data.json
content/browser/schemas/chrome_settings_overrides.json
content/browser/schemas/commands.json content/browser/schemas/commands.json
content/browser/schemas/context_menus.json content/browser/schemas/context_menus.json
content/browser/schemas/context_menus_internal.json content/browser/schemas/context_menus_internal.json

View File

@ -120,6 +120,7 @@ support-files =
[browser_ext_themes_icons.js] [browser_ext_themes_icons.js]
[browser_ext_topwindowid.js] [browser_ext_topwindowid.js]
[browser_ext_url_overrides_newtab.js] [browser_ext_url_overrides_newtab.js]
[browser_ext_url_overrides_home.js]
[browser_ext_webRequest.js] [browser_ext_webRequest.js]
[browser_ext_webNavigation_frameId0.js] [browser_ext_webNavigation_frameId0.js]
[browser_ext_webNavigation_getFrames.js] [browser_ext_webNavigation_getFrames.js]

View File

@ -0,0 +1,184 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
"resource://gre/modules/Preferences.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
"resource://gre/modules/AddonManager.jsm");
// Named this way so they correspond to the extensions
const HOME_URI_2 = "http://example.com/";
const HOME_URI_3 = "http://example.org/";
const HOME_URI_4 = "http://example.net/";
add_task(function* test_multiple_extensions_overriding_home_page() {
let defaultHomePage = Preferences.get("browser.startup.homepage");
let ext1 = ExtensionTestUtils.loadExtension({
manifest: {"chrome_settings_overrides": {}},
useAddonManager: "temporary",
});
let ext2 = ExtensionTestUtils.loadExtension({
manifest: {"chrome_settings_overrides": {homepage: HOME_URI_2}},
useAddonManager: "temporary",
});
let ext3 = ExtensionTestUtils.loadExtension({
manifest: {"chrome_settings_overrides": {homepage: HOME_URI_3}},
useAddonManager: "temporary",
});
let ext4 = ExtensionTestUtils.loadExtension({
manifest: {"chrome_settings_overrides": {homepage: HOME_URI_4}},
useAddonManager: "temporary",
});
yield ext1.startup();
is(Preferences.get("browser.startup.homepage"), defaultHomePage,
"Home url should be the default");
// Because we are expecting the pref to change when we start or unload, we
// need to wait on a pref change. This is because the pref management is
// async and can happen after the startup/unload is finished.
let prefPromise = promisePrefChangeObserved("browser.startup.homepage");
yield ext2.startup();
yield prefPromise;
ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_2),
"Home url should be overridden by the second extension.");
// Because we are unloading an earlier extension, browser.startup.homepage won't change
yield ext1.unload();
ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_2),
"Home url should be overridden by the second extension.");
prefPromise = promisePrefChangeObserved("browser.startup.homepage");
yield ext3.startup();
yield prefPromise;
ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_3),
"Home url should be overridden by the third extension.");
// Because we are unloading an earlier extension, browser.startup.homepage won't change
yield ext2.unload();
ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_3),
"Home url should be overridden by the third extension.");
prefPromise = promisePrefChangeObserved("browser.startup.homepage");
yield ext4.startup();
yield prefPromise;
ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_4),
"Home url should be overridden by the third extension.");
prefPromise = promisePrefChangeObserved("browser.startup.homepage");
yield ext4.unload();
yield prefPromise;
ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_3),
"Home url should be overridden by the third extension.");
prefPromise = promisePrefChangeObserved("browser.startup.homepage");
yield ext3.unload();
yield prefPromise;
is(Preferences.get("browser.startup.homepage"), defaultHomePage,
"Home url should be reset to default");
});
const HOME_URI_1 = "http://example.com/";
const USER_URI = "http://example.edu/";
add_task(function* test_extension_setting_home_page_back() {
let defaultHomePage = Preferences.get("browser.startup.homepage");
Preferences.set("browser.startup.homepage", USER_URI);
is(Preferences.get("browser.startup.homepage"), USER_URI,
"Home url should be the user set value");
let ext1 = ExtensionTestUtils.loadExtension({
manifest: {"chrome_settings_overrides": {homepage: HOME_URI_1}},
useAddonManager: "temporary",
});
// Because we are expecting the pref to change when we start or unload, we
// need to wait on a pref change. This is because the pref management is
// async and can happen after the startup/unload is finished.
let prefPromise = promisePrefChangeObserved("browser.startup.homepage");
yield ext1.startup();
yield prefPromise;
ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_1),
"Home url should be overridden by the second extension.");
prefPromise = promisePrefChangeObserved("browser.startup.homepage");
yield ext1.unload();
yield prefPromise;
is(Preferences.get("browser.startup.homepage"), USER_URI,
"Home url should be the user set value");
Preferences.reset("browser.startup.homepage");
is(Preferences.get("browser.startup.homepage"), defaultHomePage,
"Home url should be the default");
});
add_task(function* test_disable() {
let defaultHomePage = Preferences.get("browser.startup.homepage");
const ID = "id@tests.mozilla.org";
let ext1 = ExtensionTestUtils.loadExtension({
manifest: {
applications: {
gecko: {
id: ID,
},
},
"chrome_settings_overrides": {
homepage: HOME_URI_1,
},
},
useAddonManager: "temporary",
});
let prefPromise = promisePrefChangeObserved("browser.startup.homepage");
yield ext1.startup();
yield prefPromise;
ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_1),
"Home url should be overridden by the extension.");
let addon = yield AddonManager.getAddonByID(ID);
is(addon.id, ID);
prefPromise = promisePrefChangeObserved("browser.startup.homepage");
addon.userDisabled = true;
yield prefPromise;
is(Preferences.get("browser.startup.homepage"), defaultHomePage,
"Home url should be the default");
prefPromise = promisePrefChangeObserved("browser.startup.homepage");
addon.userDisabled = false;
yield prefPromise;
ok(Preferences.get("browser.startup.homepage").endsWith(HOME_URI_1),
"Home url should be overridden by the extension.");
prefPromise = promisePrefChangeObserved("browser.startup.homepage");
yield ext1.unload();
yield prefPromise;
is(Preferences.get("browser.startup.homepage"), defaultHomePage,
"Home url should be the default");
});

View File

@ -16,6 +16,7 @@
* getListStyleImage getPanelForNode * getListStyleImage getPanelForNode
* awaitExtensionPanel awaitPopupResize * awaitExtensionPanel awaitPopupResize
* promiseContentDimensions alterContent * promiseContentDimensions alterContent
* promisePrefChangeObserved
*/ */
const {AppConstants} = Cu.import("resource://gre/modules/AppConstants.jsm", {}); const {AppConstants} = Cu.import("resource://gre/modules/AppConstants.jsm", {});
@ -348,3 +349,11 @@ function closePageAction(extension, win = window) {
return Promise.resolve(); return Promise.resolve();
} }
function promisePrefChangeObserved(pref) {
return new Promise((resolve, reject) =>
Preferences.observe(pref, function prefObserver() {
Preferences.ignore(pref, prefObserver);
resolve();
}));
}

View File

@ -33,6 +33,7 @@ tags = trackingprotection
[browser_privatebrowsing_downloadLastDir_toggle.js] [browser_privatebrowsing_downloadLastDir_toggle.js]
[browser_privatebrowsing_favicon.js] [browser_privatebrowsing_favicon.js]
[browser_privatebrowsing_geoprompt.js] [browser_privatebrowsing_geoprompt.js]
tags = geolocation
[browser_privatebrowsing_lastpbcontextexited.js] [browser_privatebrowsing_lastpbcontextexited.js]
[browser_privatebrowsing_localStorage.js] [browser_privatebrowsing_localStorage.js]
[browser_privatebrowsing_localStorage_before_after.js] [browser_privatebrowsing_localStorage_before_after.js]

View File

@ -175,7 +175,7 @@ ContentRestoreInternal.prototype = {
* Start loading the current page. When the data has finished loading from the * Start loading the current page. When the data has finished loading from the
* network, finishCallback is called. Returns true if the load was successful. * network, finishCallback is called. Returns true if the load was successful.
*/ */
restoreTabContent: function (loadArguments, isRemotenessUpdate, finishCallback) { restoreTabContent(loadArguments, isRemotenessUpdate, finishCallback) {
let tabData = this._tabData; let tabData = this._tabData;
this._tabData = null; this._tabData = null;
@ -199,7 +199,7 @@ ContentRestoreInternal.prototype = {
// same state it was before the load started then trigger the load. // same state it was before the load started then trigger the load.
let referrer = loadArguments.referrer ? let referrer = loadArguments.referrer ?
Utils.makeURI(loadArguments.referrer) : null; Utils.makeURI(loadArguments.referrer) : null;
let referrerPolicy = ('referrerPolicy' in loadArguments let referrerPolicy = ("referrerPolicy" in loadArguments
? loadArguments.referrerPolicy ? loadArguments.referrerPolicy
: Ci.nsIHttpChannel.REFERRER_POLICY_UNSET); : Ci.nsIHttpChannel.REFERRER_POLICY_UNSET);
let postData = loadArguments.postData ? let postData = loadArguments.postData ?
@ -243,11 +243,14 @@ ContentRestoreInternal.prototype = {
} }
return true; return true;
} catch (ex if ex instanceof Ci.nsIException) { } catch (ex) {
// Ignore page load errors, but return false to signal that the load never if (ex instanceof Ci.nsIException) {
// happened. // Ignore page load errors, but return false to signal that the load never
return false; // happened.
return false;
}
} }
return null;
}, },
/** /**
@ -281,11 +284,11 @@ ContentRestoreInternal.prototype = {
* position. The restore is complete when this function exits. It should be * position. The restore is complete when this function exits. It should be
* called when the "load" event fires for the restoring tab. * called when the "load" event fires for the restoring tab.
*/ */
restoreDocument: function () { restoreDocument() {
if (!this._restoringDocument) { if (!this._restoringDocument) {
return; return;
} }
let {entry, pageStyle, formdata, scrollPositions} = this._restoringDocument; let {pageStyle, formdata, scrollPositions} = this._restoringDocument;
this._restoringDocument = null; this._restoringDocument = null;
let window = this.docShell.QueryInterface(Ci.nsIInterfaceRequestor) let window = this.docShell.QueryInterface(Ci.nsIInterfaceRequestor)
@ -305,7 +308,7 @@ ContentRestoreInternal.prototype = {
* case, it's called before restoreDocument, so it cannot clear * case, it's called before restoreDocument, so it cannot clear
* _restoringDocument. * _restoringDocument.
*/ */
resetRestore: function () { resetRestore() {
this._tabData = null; this._tabData = null;
if (this._historyListener) { if (this._historyListener) {
@ -338,18 +341,18 @@ HistoryListener.prototype = {
Ci.nsISupportsWeakReference Ci.nsISupportsWeakReference
]), ]),
uninstall: function () { uninstall() {
let shistory = this.webNavigation.sessionHistory; let shistory = this.webNavigation.sessionHistory;
if (shistory) { if (shistory) {
shistory.removeSHistoryListener(this); shistory.removeSHistoryListener(this);
} }
}, },
OnHistoryGoBack: function(backURI) { return true; }, OnHistoryGoBack(backURI) { return true; },
OnHistoryGoForward: function(forwardURI) { return true; }, OnHistoryGoForward(forwardURI) { return true; },
OnHistoryGotoIndex: function(index, gotoURI) { return true; }, OnHistoryGotoIndex(index, gotoURI) { return true; },
OnHistoryPurge: function(numEntries) { return true; }, OnHistoryPurge(numEntries) { return true; },
OnHistoryReplaceEntry: function(index) {}, OnHistoryReplaceEntry(index) {},
// This will be called for a pending tab when loadURI(uri) is called where // This will be called for a pending tab when loadURI(uri) is called where
// the given |uri| only differs in the fragment. // the given |uri| only differs in the fragment.
@ -408,11 +411,11 @@ ProgressListener.prototype = {
Ci.nsISupportsWeakReference Ci.nsISupportsWeakReference
]), ]),
uninstall: function() { uninstall() {
this.webProgress.removeProgressListener(this); this.webProgress.removeProgressListener(this);
}, },
onStateChange: function(webProgress, request, stateFlags, status) { onStateChange(webProgress, request, stateFlags, status) {
let {STATE_IS_WINDOW, STATE_STOP, STATE_START} = Ci.nsIWebProgressListener; let {STATE_IS_WINDOW, STATE_STOP, STATE_START} = Ci.nsIWebProgressListener;
if (!webProgress.isTopLevel || !(stateFlags & STATE_IS_WINDOW)) { if (!webProgress.isTopLevel || !(stateFlags & STATE_IS_WINDOW)) {
return; return;
@ -427,8 +430,8 @@ ProgressListener.prototype = {
} }
}, },
onLocationChange: function() {}, onLocationChange() {},
onProgressChange: function() {}, onProgressChange() {},
onStatusChange: function() {}, onStatusChange() {},
onSecurityChange: function() {}, onSecurityChange() {},
}; };

View File

@ -10,11 +10,11 @@ this.EXPORTED_SYMBOLS = ["DocShellCapabilities"];
* The external API exported by this module. * The external API exported by this module.
*/ */
this.DocShellCapabilities = Object.freeze({ this.DocShellCapabilities = Object.freeze({
collect: function (docShell) { collect(docShell) {
return DocShellCapabilitiesInternal.collect(docShell); return DocShellCapabilitiesInternal.collect(docShell);
}, },
restore: function (docShell, disallow) { restore(docShell, disallow) {
return DocShellCapabilitiesInternal.restore(docShell, disallow); return DocShellCapabilitiesInternal.restore(docShell, disallow);
}, },
}); });
@ -29,7 +29,7 @@ var DocShellCapabilitiesInternal = {
// properties. // properties.
caps: null, caps: null,
allCapabilities: function (docShell) { allCapabilities(docShell) {
if (!this.caps) { if (!this.caps) {
let keys = Object.keys(docShell); let keys = Object.keys(docShell);
this.caps = keys.filter(k => k.startsWith("allow")).map(k => k.slice(5)); this.caps = keys.filter(k => k.startsWith("allow")).map(k => k.slice(5));
@ -37,12 +37,12 @@ var DocShellCapabilitiesInternal = {
return this.caps; return this.caps;
}, },
collect: function (docShell) { collect(docShell) {
let caps = this.allCapabilities(docShell); let caps = this.allCapabilities(docShell);
return caps.filter(cap => !docShell["allow" + cap]); return caps.filter(cap => !docShell["allow" + cap]);
}, },
restore: function (docShell, disallow) { restore(docShell, disallow) {
let caps = this.allCapabilities(docShell); let caps = this.allCapabilities(docShell);
for (let cap of caps) for (let cap of caps)
docShell["allow" + cap] = !disallow.has(cap); docShell["allow" + cap] = !disallow.has(cap);

View File

@ -80,7 +80,7 @@ FrameTreeInternal.prototype = {
* *
* @param obs (object) * @param obs (object)
*/ */
addObserver: function (obs) { addObserver(obs) {
this._observers.add(obs); this._observers.add(obs);
}, },
@ -89,7 +89,7 @@ FrameTreeInternal.prototype = {
* *
* @param method (string) * @param method (string)
*/ */
notifyObservers: function (method) { notifyObservers(method) {
for (let obs of this._observers) { for (let obs of this._observers) {
if (obs.hasOwnProperty(method)) { if (obs.hasOwnProperty(method)) {
obs[method](); obs[method]();
@ -104,7 +104,7 @@ FrameTreeInternal.prototype = {
* @param frame (nsIDOMWindow) * @param frame (nsIDOMWindow)
* @return bool * @return bool
*/ */
contains: function (frame) { contains(frame) {
return this._frames.has(frame); return this._frames.has(frame);
}, },
@ -124,7 +124,7 @@ FrameTreeInternal.prototype = {
* @param cb (function) * @param cb (function)
* @return object * @return object
*/ */
map: function (cb) { map(cb) {
let frames = this._frames; let frames = this._frames;
function walk(frame) { function walk(frame) {
@ -169,7 +169,7 @@ FrameTreeInternal.prototype = {
* @param cb (function) * @param cb (function)
* This callback receives the current frame as the only argument. * This callback receives the current frame as the only argument.
*/ */
forEach: function (cb) { forEach(cb) {
let frames = this._frames; let frames = this._frames;
function walk(frame) { function walk(frame) {
@ -196,7 +196,7 @@ FrameTreeInternal.prototype = {
* @param index (int) * @param index (int)
* The index in the given frame's parent's child list. * The index in the given frame's parent's child list.
*/ */
collect: function (frame, index = 0) { collect(frame, index = 0) {
// Mark the given frame as contained in the frame tree. // Mark the given frame as contained in the frame tree.
this._frames.set(frame, index); this._frames.set(frame, index);
@ -211,7 +211,7 @@ FrameTreeInternal.prototype = {
* - new documents that start loading to clear the current frame tree; * - new documents that start loading to clear the current frame tree;
* - completed document loads to recollect reachable frames. * - completed document loads to recollect reachable frames.
*/ */
onStateChange: function (webProgress, request, stateFlags, status) { onStateChange(webProgress, request, stateFlags, status) {
// Ignore state changes for subframes because we're only interested in the // Ignore state changes for subframes because we're only interested in the
// top-document starting or stopping its load. We thus only care about any // top-document starting or stopping its load. We thus only care about any
// changes to the root of the frame tree, not to any of its nodes/leafs. // changes to the root of the frame tree, not to any of its nodes/leafs.
@ -244,10 +244,10 @@ FrameTreeInternal.prototype = {
}, },
// Unused nsIWebProgressListener methods. // Unused nsIWebProgressListener methods.
onLocationChange: function () {}, onLocationChange() {},
onProgressChange: function () {}, onProgressChange() {},
onSecurityChange: function () {}, onSecurityChange() {},
onStatusChange: function () {}, onStatusChange() {},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference]) Ci.nsISupportsWeakReference])

View File

@ -28,14 +28,14 @@ GlobalStateInternal.prototype = {
/** /**
* Get all value from the global state. * Get all value from the global state.
*/ */
getState: function() { getState() {
return this.state; return this.state;
}, },
/** /**
* Clear all currently stored global state. * Clear all currently stored global state.
*/ */
clear: function() { clear() {
this.state = {}; this.state = {};
}, },
@ -46,7 +46,7 @@ GlobalStateInternal.prototype = {
* A key the value is stored under. * A key the value is stored under.
* @return The value stored at aKey, or an empty string if no value is set. * @return The value stored at aKey, or an empty string if no value is set.
*/ */
get: function(aKey) { get(aKey) {
return this.state[aKey] || ""; return this.state[aKey] || "";
}, },
@ -56,7 +56,7 @@ GlobalStateInternal.prototype = {
* @param aKey * @param aKey
* A key to store the value under. * A key to store the value under.
*/ */
set: function(aKey, aStringValue) { set(aKey, aStringValue) {
this.state[aKey] = aStringValue; this.state[aKey] = aStringValue;
}, },
@ -66,7 +66,7 @@ GlobalStateInternal.prototype = {
* @param aKey * @param aKey
* A key to delete the value for. * A key to delete the value for.
*/ */
delete: function(aKey) { delete(aKey) {
delete this.state[aKey]; delete this.state[aKey];
}, },
@ -78,7 +78,7 @@ GlobalStateInternal.prototype = {
* @param aState * @param aState
* A state object to extract global state from to be set. * A state object to extract global state from to be set.
*/ */
setFromState: function (aState) { setFromState(aState) {
this.state = (aState && aState.global) || {}; this.state = (aState && aState.global) || {};
} }
}; };

View File

@ -12,11 +12,11 @@ const Ci = Components.interfaces;
* The external API exported by this module. * The external API exported by this module.
*/ */
this.PageStyle = Object.freeze({ this.PageStyle = Object.freeze({
collect: function (docShell, frameTree) { collect(docShell, frameTree) {
return PageStyleInternal.collect(docShell, frameTree); return PageStyleInternal.collect(docShell, frameTree);
}, },
restoreTree: function (docShell, data) { restoreTree(docShell, data) {
PageStyleInternal.restoreTree(docShell, data); PageStyleInternal.restoreTree(docShell, data);
} }
}); });
@ -28,7 +28,7 @@ var PageStyleInternal = {
/** /**
* Collects the selected style sheet sets for all reachable frames. * Collects the selected style sheet sets for all reachable frames.
*/ */
collect: function (docShell, frameTree) { collect(docShell, frameTree) {
let result = frameTree.map(({document: doc}) => { let result = frameTree.map(({document: doc}) => {
let style; let style;
@ -71,23 +71,23 @@ var PageStyleInternal = {
* ] * ]
* } * }
*/ */
restoreTree: function (docShell, data) { restoreTree(docShell, data) {
let disabled = data.disabled || false; let disabled = data.disabled || false;
let markupDocumentViewer = let markupDocumentViewer =
docShell.contentViewer; docShell.contentViewer;
markupDocumentViewer.authorStyleDisabled = disabled; markupDocumentViewer.authorStyleDisabled = disabled;
function restoreFrame(root, data) { function restoreFrame(root, frameData) {
if (data.hasOwnProperty("pageStyle")) { if (frameData.hasOwnProperty("pageStyle")) {
root.document.selectedStyleSheetSet = data.pageStyle; root.document.selectedStyleSheetSet = frameData.pageStyle;
} }
if (!data.hasOwnProperty("children")) { if (!frameData.hasOwnProperty("children")) {
return; return;
} }
let frames = root.frames; let frames = root.frames;
data.children.forEach((child, index) => { frameData.children.forEach((child, index) => {
if (child && index < frames.length) { if (child && index < frames.length) {
restoreFrame(frames[index], child); restoreFrame(frames[index], child);
} }

View File

@ -26,7 +26,7 @@ this.PrivacyFilter = Object.freeze({
* @param data The session storage data as collected from a tab. * @param data The session storage data as collected from a tab.
* @return object * @return object
*/ */
filterSessionStorageData: function (data) { filterSessionStorageData(data) {
let retval = {}; let retval = {};
for (let host of Object.keys(data)) { for (let host of Object.keys(data)) {
@ -46,12 +46,12 @@ this.PrivacyFilter = Object.freeze({
* @param data The form data as collected from a tab. * @param data The form data as collected from a tab.
* @return object * @return object
*/ */
filterFormData: function (data) { filterFormData(data) {
// If the given form data object has an associated URL that we are not // If the given form data object has an associated URL that we are not
// allowed to store data for, bail out. We explicitly discard data for any // allowed to store data for, bail out. We explicitly discard data for any
// children as well even if storing data for those frames would be allowed. // children as well even if storing data for those frames would be allowed.
if (data.url && !PrivacyLevel.check(data.url)) { if (data.url && !PrivacyLevel.check(data.url)) {
return; return null;
} }
let retval = {}; let retval = {};
@ -81,7 +81,7 @@ this.PrivacyFilter = Object.freeze({
* The browser state for which we remove any private windows and tabs. * The browser state for which we remove any private windows and tabs.
* The given object will be modified. * The given object will be modified.
*/ */
filterPrivateWindowsAndTabs: function (browserState) { filterPrivateWindowsAndTabs(browserState) {
// Remove private opened windows. // Remove private opened windows.
for (let i = browserState.windows.length - 1; i >= 0; i--) { for (let i = browserState.windows.length - 1; i >= 0; i--) {
let win = browserState.windows[i]; let win = browserState.windows[i];
@ -113,7 +113,7 @@ this.PrivacyFilter = Object.freeze({
* The window state for which we remove any private tabs. * The window state for which we remove any private tabs.
* The given object will be modified. * The given object will be modified.
*/ */
filterPrivateTabs: function (winState) { filterPrivateTabs(winState) {
// Remove open private tabs. // Remove open private tabs.
for (let i = winState.tabs.length - 1; i >= 0 ; i--) { for (let i = winState.tabs.length - 1; i >= 0 ; i--) {
let tab = winState.tabs[i]; let tab = winState.tabs[i];

View File

@ -37,8 +37,8 @@ this.RecentlyClosedTabsAndWindowsMenuUtils = {
* Which localizable string to use for the 'restore all tabs' item. * Which localizable string to use for the 'restore all tabs' item.
* @returns A document fragment with UI items for each recently closed tab. * @returns A document fragment with UI items for each recently closed tab.
*/ */
getTabsFragment: function(aWindow, aTagName, aPrefixRestoreAll=false, getTabsFragment(aWindow, aTagName, aPrefixRestoreAll = false,
aRestoreAllLabel="menuRestoreAllTabs.label") { aRestoreAllLabel = "menuRestoreAllTabs.label") {
let doc = aWindow.document; let doc = aWindow.document;
let fragment = doc.createDocumentFragment(); let fragment = doc.createDocumentFragment();
if (SessionStore.getClosedTabCount(aWindow) != 0) { if (SessionStore.getClosedTabCount(aWindow) != 0) {
@ -67,8 +67,8 @@ this.RecentlyClosedTabsAndWindowsMenuUtils = {
* Which localizable string to use for the 'restore all windows' item. * Which localizable string to use for the 'restore all windows' item.
* @returns A document fragment with UI items for each recently closed window. * @returns A document fragment with UI items for each recently closed window.
*/ */
getWindowsFragment: function(aWindow, aTagName, aPrefixRestoreAll=false, getWindowsFragment(aWindow, aTagName, aPrefixRestoreAll = false,
aRestoreAllLabel="menuRestoreAllWindows.label") { aRestoreAllLabel = "menuRestoreAllWindows.label") {
let closedWindowData = SessionStore.getClosedWindowData(false); let closedWindowData = SessionStore.getClosedWindowData(false);
let doc = aWindow.document; let doc = aWindow.document;
let fragment = doc.createDocumentFragment(); let fragment = doc.createDocumentFragment();
@ -104,7 +104,7 @@ this.RecentlyClosedTabsAndWindowsMenuUtils = {
* @param aEvent * @param aEvent
* The event when the user clicks the menu item * The event when the user clicks the menu item
*/ */
_undoCloseMiddleClick: function(aEvent) { _undoCloseMiddleClick(aEvent) {
if (aEvent.button != 1) if (aEvent.button != 1)
return; return;
@ -172,7 +172,7 @@ function createEntry(aTagName, aIsWindowsFragment, aIndex, aClosedTab,
element.addEventListener("click", RecentlyClosedTabsAndWindowsMenuUtils._undoCloseMiddleClick); element.addEventListener("click", RecentlyClosedTabsAndWindowsMenuUtils._undoCloseMiddleClick);
} }
if (aIndex == 0) { if (aIndex == 0) {
element.setAttribute("key", "key_undoClose" + (aIsWindowsFragment? "Window" : "Tab")); element.setAttribute("key", "key_undoClose" + (aIsWindowsFragment ? "Window" : "Tab"));
} }
aFragment.appendChild(element); aFragment.appendChild(element);
@ -204,11 +204,11 @@ function createRestoreAllEntry(aDocument, aFragment, aPrefixRestoreAll,
restoreAllElements.setAttribute("label", navigatorBundle.GetStringFromName(aRestoreAllLabel)); restoreAllElements.setAttribute("label", navigatorBundle.GetStringFromName(aRestoreAllLabel));
restoreAllElements.setAttribute("oncommand", restoreAllElements.setAttribute("oncommand",
"for (var i = 0; i < " + aEntryCount + "; i++) undoClose" + "for (var i = 0; i < " + aEntryCount + "; i++) undoClose" +
(aIsWindowsFragment? "Window" : "Tab") + "();"); (aIsWindowsFragment ? "Window" : "Tab") + "();");
if (aPrefixRestoreAll) { if (aPrefixRestoreAll) {
aFragment.insertBefore(restoreAllElements, aFragment.firstChild); aFragment.insertBefore(restoreAllElements, aFragment.firstChild);
} else { } else {
aFragment.appendChild(aDocument.createElementNS(kNSXUL, "menuseparator")); aFragment.appendChild(aDocument.createElementNS(kNSXUL, "menuseparator"));
aFragment.appendChild(restoreAllElements); aFragment.appendChild(restoreAllElements);
} }
} }

View File

@ -24,11 +24,11 @@ const MAX_EXPIRY = Math.pow(2, 62);
* The external API implemented by the SessionCookies module. * The external API implemented by the SessionCookies module.
*/ */
this.SessionCookies = Object.freeze({ this.SessionCookies = Object.freeze({
update: function (windows) { update(windows) {
SessionCookiesInternal.update(windows); SessionCookiesInternal.update(windows);
}, },
getHostsForWindow: function (window, checkPrivacy = false) { getHostsForWindow(window, checkPrivacy = false) {
return SessionCookiesInternal.getHostsForWindow(window, checkPrivacy); return SessionCookiesInternal.getHostsForWindow(window, checkPrivacy);
}, },
@ -55,7 +55,7 @@ var SessionCookiesInternal = {
* Array of window state objects. * Array of window state objects.
* [{ tabs: [...], cookies: [...] }, ...] * [{ tabs: [...], cookies: [...] }, ...]
*/ */
update: function (windows) { update(windows) {
this._ensureInitialized(); this._ensureInitialized();
for (let window of windows) { for (let window of windows) {
@ -71,7 +71,7 @@ var SessionCookiesInternal = {
// _getCookiesForHost() will only return hosts with the right privacy // _getCookiesForHost() will only return hosts with the right privacy
// rules, so there is no need to do anything special with this call // rules, so there is no need to do anything special with this call
// to PrivacyLevel.canSave(). // to PrivacyLevel.canSave().
if (PrivacyLevel.canSave({isHttps: cookie.secure, isPinned: isPinned})) { if (PrivacyLevel.canSave({isHttps: cookie.secure, isPinned})) {
cookies.push(cookie); cookies.push(cookie);
} }
} }
@ -99,7 +99,7 @@ var SessionCookiesInternal = {
* whether we will use the deferred privacy level when * whether we will use the deferred privacy level when
* checking how much data to save on quitting. * checking how much data to save on quitting.
*/ */
getHostsForWindow: function (window, checkPrivacy = false) { getHostsForWindow(window, checkPrivacy = false) {
let hosts = {}; let hosts = {};
for (let tab of window.tabs) { for (let tab of window.tabs) {
@ -135,7 +135,7 @@ var SessionCookiesInternal = {
* Handles observers notifications that are sent whenever cookies are added, * Handles observers notifications that are sent whenever cookies are added,
* changed, or removed. Ensures that the storage is updated accordingly. * changed, or removed. Ensures that the storage is updated accordingly.
*/ */
observe: function (subject, topic, data) { observe(subject, topic, data) {
switch (data) { switch (data) {
case "added": case "added":
case "changed": case "changed":
@ -163,7 +163,7 @@ var SessionCookiesInternal = {
* If called for the first time in a session, iterates all cookies in the * If called for the first time in a session, iterates all cookies in the
* cookies service and puts them into the store if they're session cookies. * cookies service and puts them into the store if they're session cookies.
*/ */
_ensureInitialized: function () { _ensureInitialized() {
if (!this._initialized) { if (!this._initialized) {
this._reloadCookies(); this._reloadCookies();
this._initialized = true; this._initialized = true;
@ -185,7 +185,7 @@ var SessionCookiesInternal = {
* is the entry we're evaluating for a pinned tab; used only if * is the entry we're evaluating for a pinned tab; used only if
* checkPrivacy * checkPrivacy
*/ */
_extractHostsFromEntry: function (entry, hosts, checkPrivacy, isPinned) { _extractHostsFromEntry(entry, hosts, checkPrivacy, isPinned) {
let host = entry._host; let host = entry._host;
let scheme = entry._scheme; let scheme = entry._scheme;
@ -199,8 +199,7 @@ var SessionCookiesInternal = {
host = uri.host; host = uri.host;
scheme = uri.scheme; scheme = uri.scheme;
this._extractHostsFromHostScheme(host, scheme, hosts, checkPrivacy, isPinned); this._extractHostsFromHostScheme(host, scheme, hosts, checkPrivacy, isPinned);
} } catch (ex) { }
catch (ex) { }
} }
if (entry.children) { if (entry.children) {
@ -226,13 +225,12 @@ var SessionCookiesInternal = {
* is the entry we're evaluating for a pinned tab; used only if * is the entry we're evaluating for a pinned tab; used only if
* checkPrivacy * checkPrivacy
*/ */
_extractHostsFromHostScheme: _extractHostsFromHostScheme(host, scheme, hosts, checkPrivacy, isPinned) {
function (host, scheme, hosts, checkPrivacy, isPinned) {
// host and scheme may not be set (for about: urls for example), in which // host and scheme may not be set (for about: urls for example), in which
// case testing scheme will be sufficient. // case testing scheme will be sufficient.
if (/https?/.test(scheme) && !hosts[host] && if (/https?/.test(scheme) && !hosts[host] &&
(!checkPrivacy || (!checkPrivacy ||
PrivacyLevel.canSave({isHttps: scheme == "https", isPinned: isPinned}))) { PrivacyLevel.canSave({isHttps: scheme == "https", isPinned}))) {
// By setting this to true or false, we can determine when looking at // By setting this to true or false, we can determine when looking at
// the host in update() if we should check for privacy. // the host in update() if we should check for privacy.
hosts[host] = isPinned; hosts[host] = isPinned;
@ -244,7 +242,7 @@ var SessionCookiesInternal = {
/** /**
* Updates or adds a given cookie to the store. * Updates or adds a given cookie to the store.
*/ */
_updateCookie: function (cookie) { _updateCookie(cookie) {
cookie.QueryInterface(Ci.nsICookie2); cookie.QueryInterface(Ci.nsICookie2);
if (cookie.isSession) { if (cookie.isSession) {
@ -257,7 +255,7 @@ var SessionCookiesInternal = {
/** /**
* Removes a given cookie from the store. * Removes a given cookie from the store.
*/ */
_removeCookie: function (cookie) { _removeCookie(cookie) {
cookie.QueryInterface(Ci.nsICookie2); cookie.QueryInterface(Ci.nsICookie2);
if (cookie.isSession) { if (cookie.isSession) {
@ -268,7 +266,7 @@ var SessionCookiesInternal = {
/** /**
* Removes a given list of cookies from the store. * Removes a given list of cookies from the store.
*/ */
_removeCookies: function (cookies) { _removeCookies(cookies) {
for (let i = 0; i < cookies.length; i++) { for (let i = 0; i < cookies.length; i++) {
this._removeCookie(cookies.queryElementAt(i, Ci.nsICookie2)); this._removeCookie(cookies.queryElementAt(i, Ci.nsICookie2));
} }
@ -278,7 +276,7 @@ var SessionCookiesInternal = {
* Iterates all cookies in the cookies service and puts them into the store * Iterates all cookies in the cookies service and puts them into the store
* if they're session cookies. * if they're session cookies.
*/ */
_reloadCookies: function () { _reloadCookies() {
let iter = Services.cookies.enumerator; let iter = Services.cookies.enumerator;
while (iter.hasMoreElements()) { while (iter.hasMoreElements()) {
this._updateCookie(iter.getNext()); this._updateCookie(iter.getNext());
@ -358,10 +356,10 @@ var CookieStore = {
/** /**
* Returns the list of stored session cookies for a given host. * Returns the list of stored session cookies for a given host.
* *
* @param host * @param mainHost
* A string containing the host name we want to get cookies for. * A string containing the host name we want to get cookies for.
*/ */
getCookiesForHost: function (host) { getCookiesForHost(mainHost) {
let cookies = []; let cookies = [];
let appendCookiesForHost = host => { let appendCookiesForHost = host => {
@ -383,7 +381,7 @@ var CookieStore = {
// <.example.com>. We will find those variants with a leading dot in the // <.example.com>. We will find those variants with a leading dot in the
// map if the Set-Cookie header had a domain= attribute, i.e. the cookie // map if the Set-Cookie header had a domain= attribute, i.e. the cookie
// will be stored for a parent domain and we send it for any subdomain. // will be stored for a parent domain and we send it for any subdomain.
for (let variant of [host, ...getPossibleSubdomainVariants(host)]) { for (let variant of [mainHost, ...getPossibleSubdomainVariants(mainHost)]) {
appendCookiesForHost(variant); appendCookiesForHost(variant);
} }
@ -396,7 +394,7 @@ var CookieStore = {
* @param cookie * @param cookie
* The nsICookie2 object to add to the storage. * The nsICookie2 object to add to the storage.
*/ */
set: function (cookie) { set(cookie) {
let jscookie = {host: cookie.host, value: cookie.value}; let jscookie = {host: cookie.host, value: cookie.value};
// Only add properties with non-default values to save a few bytes. // Only add properties with non-default values to save a few bytes.
@ -433,14 +431,14 @@ var CookieStore = {
* @param cookie * @param cookie
* The nsICookie2 object to be removed from storage. * The nsICookie2 object to be removed from storage.
*/ */
delete: function (cookie) { delete(cookie) {
this._ensureMap(cookie).delete(cookie.name); this._ensureMap(cookie).delete(cookie.name);
}, },
/** /**
* Removes all cookies. * Removes all cookies.
*/ */
clear: function () { clear() {
this._hosts.clear(); this._hosts.clear();
}, },
@ -453,7 +451,7 @@ var CookieStore = {
* @return The newly created Map instance mapping cookie names to * @return The newly created Map instance mapping cookie names to
* internal jscookies, in the given path of the given host. * internal jscookies, in the given path of the given host.
*/ */
_ensureMap: function (cookie) { _ensureMap(cookie) {
if (!this._hosts.has(cookie.host)) { if (!this._hosts.has(cookie.host)) {
this._hosts.set(cookie.host, new Map()); this._hosts.set(cookie.host, new Map());
} }

View File

@ -66,19 +66,19 @@ this.SessionFile = {
/** /**
* Read the contents of the session file, asynchronously. * Read the contents of the session file, asynchronously.
*/ */
read: function () { read() {
return SessionFileInternal.read(); return SessionFileInternal.read();
}, },
/** /**
* Write the contents of the session file, asynchronously. * Write the contents of the session file, asynchronously.
*/ */
write: function (aData) { write(aData) {
return SessionFileInternal.write(aData); return SessionFileInternal.write(aData);
}, },
/** /**
* Wipe the contents of the session file, asynchronously. * Wipe the contents of the session file, asynchronously.
*/ */
wipe: function () { wipe() {
return SessionFileInternal.wipe(); return SessionFileInternal.wipe();
}, },
@ -226,32 +226,34 @@ var SessionFileInternal = {
let source = yield OS.File.read(path, { encoding: "utf-8" }); let source = yield OS.File.read(path, { encoding: "utf-8" });
let parsed = JSON.parse(source); let parsed = JSON.parse(source);
if (!SessionStore.isFormatVersionCompatible(parsed.version || ["sessionrestore", 0] /*fallback for old versions*/)) { if (!SessionStore.isFormatVersionCompatible(parsed.version || ["sessionrestore", 0] /* fallback for old versions*/)) {
// Skip sessionstore files that we don't understand. // Skip sessionstore files that we don't understand.
Cu.reportError("Cannot extract data from Session Restore file " + path + ". Wrong format/version: " + JSON.stringify(parsed.version) + "."); Cu.reportError("Cannot extract data from Session Restore file " + path + ". Wrong format/version: " + JSON.stringify(parsed.version) + ".");
continue; continue;
} }
result = { result = {
origin: key, origin: key,
source: source, source,
parsed: parsed parsed
}; };
Telemetry.getHistogramById("FX_SESSION_RESTORE_CORRUPT_FILE"). Telemetry.getHistogramById("FX_SESSION_RESTORE_CORRUPT_FILE").
add(false); add(false);
Telemetry.getHistogramById("FX_SESSION_RESTORE_READ_FILE_MS"). Telemetry.getHistogramById("FX_SESSION_RESTORE_READ_FILE_MS").
add(Date.now() - startMs); add(Date.now() - startMs);
break; break;
} catch (ex if ex instanceof OS.File.Error && ex.becauseNoSuchFile) { } catch (ex) {
exists = false; if (ex instanceof OS.File.Error && ex.becauseNoSuchFile) {
} catch (ex if ex instanceof OS.File.Error) { exists = false;
// The file might be inaccessible due to wrong permissions } else if (ex instanceof OS.File.Error) {
// or similar failures. We'll just count it as "corrupted". // The file might be inaccessible due to wrong permissions
console.error("Could not read session file ", ex, ex.stack); // or similar failures. We'll just count it as "corrupted".
corrupted = true; console.error("Could not read session file ", ex, ex.stack);
} catch (ex if ex instanceof SyntaxError) { corrupted = true;
console.error("Corrupt session file (invalid JSON found) ", ex, ex.stack); } else if (ex instanceof SyntaxError) {
// File is corrupted, try next file console.error("Corrupt session file (invalid JSON found) ", ex, ex.stack);
corrupted = true; // File is corrupted, try next file
corrupted = true;
}
} finally { } finally {
if (exists) { if (exists) {
noFilesFound = false; noFilesFound = false;
@ -310,7 +312,7 @@ var SessionFileInternal = {
return SessionWorker.post(...args) return SessionWorker.post(...args)
}), }),
write: function (aData) { write(aData) {
if (RunState.isClosed) { if (RunState.isClosed) {
return Promise.reject(new Error("SessionFile is closed")); return Promise.reject(new Error("SessionFile is closed"));
} }
@ -377,12 +379,12 @@ var SessionFileInternal = {
}); });
}, },
wipe: function () { wipe() {
return this._postToWorker("wipe"); return this._postToWorker("wipe");
}, },
_recordTelemetry: function(telemetry) { _recordTelemetry(telemetry) {
for (let id of Object.keys(telemetry)){ for (let id of Object.keys(telemetry)) {
let value = telemetry[id]; let value = telemetry[id];
let samples = []; let samples = [];
if (Array.isArray(value)) { if (Array.isArray(value)) {

View File

@ -15,12 +15,12 @@ XPCOMUtils.defineLazyModuleGetter(this, "Utils",
"resource://gre/modules/sessionstore/Utils.jsm"); "resource://gre/modules/sessionstore/Utils.jsm");
// An encoder to UTF-8. // An encoder to UTF-8.
XPCOMUtils.defineLazyGetter(this, "gEncoder", function () { XPCOMUtils.defineLazyGetter(this, "gEncoder", function() {
return new TextEncoder(); return new TextEncoder();
}); });
// A decoder. // A decoder.
XPCOMUtils.defineLazyGetter(this, "gDecoder", function () { XPCOMUtils.defineLazyGetter(this, "gDecoder", function() {
return new TextDecoder(); return new TextDecoder();
}); });
@ -39,7 +39,7 @@ var SessionMigrationInternal = {
* The complete state is then wrapped into the "about:welcomeback" page as * The complete state is then wrapped into the "about:welcomeback" page as
* form field info to be restored when restoring the state. * form field info to be restored when restoring the state.
*/ */
convertState: function(aStateObj) { convertState(aStateObj) {
let state = { let state = {
selectedWindow: aStateObj.selectedWindow, selectedWindow: aStateObj.selectedWindow,
_closedWindows: [] _closedWindows: []
@ -71,7 +71,7 @@ var SessionMigrationInternal = {
/** /**
* Asynchronously read session restore state (JSON) from a path * Asynchronously read session restore state (JSON) from a path
*/ */
readState: function(aPath) { readState(aPath) {
return Task.spawn(function*() { return Task.spawn(function*() {
let bytes = yield OS.File.read(aPath); let bytes = yield OS.File.read(aPath);
let text = gDecoder.decode(bytes); let text = gDecoder.decode(bytes);
@ -82,7 +82,7 @@ var SessionMigrationInternal = {
/** /**
* Asynchronously write session restore state as JSON to a path * Asynchronously write session restore state as JSON to a path
*/ */
writeState: function(aPath, aState) { writeState(aPath, aState) {
let bytes = gEncoder.encode(JSON.stringify(aState)); let bytes = gEncoder.encode(JSON.stringify(aState));
return OS.File.writeAtomic(aPath, bytes, {tmpPath: aPath + ".tmp"}); return OS.File.writeAtomic(aPath, bytes, {tmpPath: aPath + ".tmp"});
} }
@ -92,7 +92,7 @@ var SessionMigration = {
/** /**
* Migrate a limited set of session data from one path to another. * Migrate a limited set of session data from one path to another.
*/ */
migrate: function(aFromPath, aToPath) { migrate(aFromPath, aToPath) {
return Task.spawn(function*() { return Task.spawn(function*() {
let inState = yield SessionMigrationInternal.readState(aFromPath); let inState = yield SessionMigrationInternal.readState(aFromPath);
let outState = SessionMigrationInternal.convertState(inState); let outState = SessionMigrationInternal.convertState(inState);

View File

@ -31,7 +31,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm"); "resource://gre/modules/PrivateBrowsingUtils.jsm");
// Minimal interval between two save operations (in milliseconds). // Minimal interval between two save operations (in milliseconds).
XPCOMUtils.defineLazyGetter(this, "gInterval", function () { XPCOMUtils.defineLazyGetter(this, "gInterval", function() {
const PREF = "browser.sessionstore.interval"; const PREF = "browser.sessionstore.interval";
// Observer that updates the cached value when the preference changes. // Observer that updates the cached value when the preference changes.
@ -54,7 +54,7 @@ function notify(subject, topic) {
// TelemetryStopwatch helper functions. // TelemetryStopwatch helper functions.
function stopWatch(method) { function stopWatch(method) {
return function (...histograms) { return function(...histograms) {
for (let hist of histograms) { for (let hist of histograms) {
TelemetryStopwatch[method]("FX_SESSION_RESTORE_" + hist); TelemetryStopwatch[method]("FX_SESSION_RESTORE_" + hist);
} }
@ -72,7 +72,7 @@ this.SessionSaver = Object.freeze({
/** /**
* Immediately saves the current session to disk. * Immediately saves the current session to disk.
*/ */
run: function () { run() {
return SessionSaverInternal.run(); return SessionSaverInternal.run();
}, },
@ -81,7 +81,7 @@ this.SessionSaver = Object.freeze({
* another delayed run be scheduled already, we will ignore the given delay * another delayed run be scheduled already, we will ignore the given delay
* and state saving may occur a little earlier. * and state saving may occur a little earlier.
*/ */
runDelayed: function () { runDelayed() {
SessionSaverInternal.runDelayed(); SessionSaverInternal.runDelayed();
}, },
@ -89,14 +89,14 @@ this.SessionSaver = Object.freeze({
* Sets the last save time to the current time. This will cause us to wait for * Sets the last save time to the current time. This will cause us to wait for
* at least the configured interval when runDelayed() is called next. * at least the configured interval when runDelayed() is called next.
*/ */
updateLastSaveTime: function () { updateLastSaveTime() {
SessionSaverInternal.updateLastSaveTime(); SessionSaverInternal.updateLastSaveTime();
}, },
/** /**
* Cancels all pending session saves. * Cancels all pending session saves.
*/ */
cancel: function () { cancel() {
SessionSaverInternal.cancel(); SessionSaverInternal.cancel();
} }
}); });
@ -121,7 +121,7 @@ var SessionSaverInternal = {
/** /**
* Immediately saves the current session to disk. * Immediately saves the current session to disk.
*/ */
run: function () { run() {
return this._saveState(true /* force-update all windows */); return this._saveState(true /* force-update all windows */);
}, },
@ -134,7 +134,7 @@ var SessionSaverInternal = {
* The minimum delay in milliseconds to wait for until we collect and * The minimum delay in milliseconds to wait for until we collect and
* save the current session. * save the current session.
*/ */
runDelayed: function (delay = 2000) { runDelayed(delay = 2000) {
// Bail out if there's a pending run. // Bail out if there's a pending run.
if (this._timeoutID) { if (this._timeoutID) {
return; return;
@ -151,14 +151,14 @@ var SessionSaverInternal = {
* Sets the last save time to the current time. This will cause us to wait for * Sets the last save time to the current time. This will cause us to wait for
* at least the configured interval when runDelayed() is called next. * at least the configured interval when runDelayed() is called next.
*/ */
updateLastSaveTime: function () { updateLastSaveTime() {
this._lastSaveTime = Date.now(); this._lastSaveTime = Date.now();
}, },
/** /**
* Cancels all pending session saves. * Cancels all pending session saves.
*/ */
cancel: function () { cancel() {
clearTimeout(this._timeoutID); clearTimeout(this._timeoutID);
this._timeoutID = null; this._timeoutID = null;
}, },
@ -170,7 +170,7 @@ var SessionSaverInternal = {
* Forces us to recollect data for all windows and will bypass and * Forces us to recollect data for all windows and will bypass and
* update the corresponding caches. * update the corresponding caches.
*/ */
_saveState: function (forceUpdateAllWindows = false) { _saveState(forceUpdateAllWindows = false) {
// Cancel any pending timeouts. // Cancel any pending timeouts.
this.cancel(); this.cancel();
@ -241,7 +241,7 @@ var SessionSaverInternal = {
* _saveState() to collect data again (with a cache hit rate of hopefully * _saveState() to collect data again (with a cache hit rate of hopefully
* 100%) and write to disk afterwards. * 100%) and write to disk afterwards.
*/ */
_saveStateAsync: function () { _saveStateAsync() {
// Allow scheduling delayed saves again. // Allow scheduling delayed saves again.
this._timeoutID = null; this._timeoutID = null;
@ -252,7 +252,7 @@ var SessionSaverInternal = {
/** /**
* Write the given state object to disk. * Write the given state object to disk.
*/ */
_writeState: function (state) { _writeState(state) {
// We update the time stamp before writing so that we don't write again // We update the time stamp before writing so that we don't write again
// too soon, if saving is requested before the write completes. Without // too soon, if saving is requested before the write completes. Without
// this update we may save repeatedly if actions cause a runDelayed // this update we may save repeatedly if actions cause a runDelayed

View File

@ -33,7 +33,7 @@ this.SessionStorage = Object.freeze({
* session storage data as strings. For example: * session storage data as strings. For example:
* {"example.com": {"key": "value", "my_number": "123"}} * {"example.com": {"key": "value", "my_number": "123"}}
*/ */
collect: function (docShell, frameTree) { collect(docShell, frameTree) {
return SessionStorageInternal.collect(docShell, frameTree); return SessionStorageInternal.collect(docShell, frameTree);
}, },
@ -46,7 +46,7 @@ this.SessionStorage = Object.freeze({
* keys and per-host session storage data as strings. For example: * keys and per-host session storage data as strings. For example:
* {"example.com": {"key": "value", "my_number": "123"}} * {"example.com": {"key": "value", "my_number": "123"}}
*/ */
restore: function (aDocShell, aStorageData) { restore(aDocShell, aStorageData) {
SessionStorageInternal.restore(aDocShell, aStorageData); SessionStorageInternal.restore(aDocShell, aStorageData);
}, },
}); });
@ -62,7 +62,7 @@ var SessionStorageInternal = {
* session storage data as strings. For example: * session storage data as strings. For example:
* {"example.com": {"key": "value", "my_number": "123"}} * {"example.com": {"key": "value", "my_number": "123"}}
*/ */
collect: function (docShell, frameTree) { collect(docShell, frameTree) {
let data = {}; let data = {};
let visitedOrigins = new Set(); let visitedOrigins = new Set();
@ -108,7 +108,7 @@ var SessionStorageInternal = {
* keys and per-host session storage data as strings. For example: * keys and per-host session storage data as strings. For example:
* {"example.com": {"key": "value", "my_number": "123"}} * {"example.com": {"key": "value", "my_number": "123"}}
*/ */
restore: function (aDocShell, aStorageData) { restore(aDocShell, aStorageData) {
for (let origin of Object.keys(aStorageData)) { for (let origin of Object.keys(aStorageData)) {
let data = aStorageData[origin]; let data = aStorageData[origin];
@ -149,7 +149,7 @@ var SessionStorageInternal = {
* @param aDocShell * @param aDocShell
* A tab's docshell (containing the sessionStorage) * A tab's docshell (containing the sessionStorage)
*/ */
_readEntry: function (aPrincipal, aDocShell) { _readEntry(aPrincipal, aDocShell) {
let hostData = {}; let hostData = {};
let storage; let storage;

View File

@ -326,7 +326,7 @@ this.SessionStore = {
SessionStoreInternal.restoreLastSession(); SessionStoreInternal.restoreLastSession();
}, },
getCurrentState: function (aUpdateAll) { getCurrentState(aUpdateAll) {
return SessionStoreInternal.getCurrentState(aUpdateAll); return SessionStoreInternal.getCurrentState(aUpdateAll);
}, },
@ -383,7 +383,7 @@ this.SessionStore = {
* The browser state for which we remove worth-saving tabs. * The browser state for which we remove worth-saving tabs.
* The given object will be modified. * The given object will be modified.
*/ */
keepOnlyWorthSavingTabs: function (aState) { keepOnlyWorthSavingTabs(aState) {
for (let i = aState.windows.length - 1; i >= 0; i--) { for (let i = aState.windows.length - 1; i >= 0; i--) {
let win = aState.windows[i]; let win = aState.windows[i];
for (let j = win.tabs.length - 1; j >= 0; j--) { for (let j = win.tabs.length - 1; j >= 0; j--) {
@ -502,7 +502,7 @@ var SessionStoreInternal = {
_closedObjectsChanged: false, _closedObjectsChanged: false,
// A promise resolved once initialization is complete // A promise resolved once initialization is complete
_deferredInitialized: (function () { _deferredInitialized: (function() {
let deferred = {}; let deferred = {};
deferred.promise = new Promise((resolve, reject) => { deferred.promise = new Promise((resolve, reject) => {
@ -571,7 +571,7 @@ var SessionStoreInternal = {
/** /**
* Initialize the sessionstore service. * Initialize the sessionstore service.
*/ */
init: function () { init() {
if (this._initialized) { if (this._initialized) {
throw new Error("SessionStore.init() must only be called once!"); throw new Error("SessionStore.init() must only be called once!");
} }
@ -588,7 +588,7 @@ var SessionStoreInternal = {
/** /**
* Initialize the session using the state provided by SessionStartup * Initialize the session using the state provided by SessionStartup
*/ */
initSession: function () { initSession() {
TelemetryStopwatch.start("FX_SESSION_RESTORE_STARTUP_INIT_SESSION_MS"); TelemetryStopwatch.start("FX_SESSION_RESTORE_STARTUP_INIT_SESSION_MS");
let state; let state;
let ss = gSessionStartup; let ss = gSessionStartup;
@ -614,8 +614,7 @@ var SessionStoreInternal = {
if (remainingState.windows.length) { if (remainingState.windows.length) {
LastSession.setState(remainingState); LastSession.setState(remainingState);
} }
} } else {
else {
// Get the last deferred session in case the user still wants to // Get the last deferred session in case the user still wants to
// restore it // restore it
LastSession.setState(state.lastSessionState); LastSession.setState(state.lastSessionState);
@ -655,8 +654,7 @@ var SessionStoreInternal = {
delete aWindow.__lastSessionWindowID; delete aWindow.__lastSessionWindowID;
}); });
} }
} } catch (ex) { debug("The session file is invalid: " + ex); }
catch (ex) { debug("The session file is invalid: " + ex); }
} }
// at this point, we've as good as resumed the session, so we can // at this point, we've as good as resumed the session, so we can
@ -669,7 +667,7 @@ var SessionStoreInternal = {
return state; return state;
}, },
_initPrefs : function() { _initPrefs() {
this._prefBranch = Services.prefs.getBranch("browser."); this._prefBranch = Services.prefs.getBranch("browser.");
gDebuggingEnabled = this._prefBranch.getBoolPref("sessionstore.debug"); gDebuggingEnabled = this._prefBranch.getBoolPref("sessionstore.debug");
@ -858,7 +856,7 @@ var SessionStoreInternal = {
} }
} }
break; break;
case "SessionStore:restoreHistoryComplete": case "SessionStore:restoreHistoryComplete": {
// Notify the tabbrowser that the tab chrome has been restored. // Notify the tabbrowser that the tab chrome has been restored.
let tabData = TabState.collect(tab); let tabData = TabState.collect(tab);
@ -902,6 +900,7 @@ var SessionStoreInternal = {
event.initEvent("SSTabRestoring", true, false); event.initEvent("SSTabRestoring", true, false);
tab.dispatchEvent(event); tab.dispatchEvent(event);
break; break;
}
case "SessionStore:restoreTabContentStarted": case "SessionStore:restoreTabContentStarted":
if (browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE) { if (browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE) {
// If a load not initiated by sessionstore was started in a // If a load not initiated by sessionstore was started in a
@ -947,7 +946,6 @@ var SessionStoreInternal = {
break; break;
default: default:
throw new Error(`received unknown message '${aMessage.name}'`); throw new Error(`received unknown message '${aMessage.name}'`);
break;
} }
}, },
@ -957,8 +955,8 @@ var SessionStoreInternal = {
* {histogramID: value, ...} An object mapping histogramIDs to the * {histogramID: value, ...} An object mapping histogramIDs to the
* value to be recorded for that ID, * value to be recorded for that ID,
*/ */
recordTelemetry: function (telemetry) { recordTelemetry(telemetry) {
for (let histogramId in telemetry){ for (let histogramId in telemetry) {
Telemetry.getHistogramById(histogramId).add(telemetry[histogramId]); Telemetry.getHistogramById(histogramId).add(telemetry[histogramId]);
} }
}, },
@ -1139,22 +1137,19 @@ var SessionStoreInternal = {
let options = {firstWindow: true, overwriteTabs: overwrite}; let options = {firstWindow: true, overwriteTabs: overwrite};
this.restoreWindows(aWindow, aInitialState, options); this.restoreWindows(aWindow, aInitialState, options);
} }
} } else {
else {
// Nothing to restore, notify observers things are complete. // Nothing to restore, notify observers things are complete.
Services.obs.notifyObservers(null, NOTIFY_WINDOWS_RESTORED, ""); Services.obs.notifyObservers(null, NOTIFY_WINDOWS_RESTORED, "");
} }
}
// this window was opened by _openWindowWithState // this window was opened by _openWindowWithState
else if (!this._isWindowLoaded(aWindow)) { } else if (!this._isWindowLoaded(aWindow)) {
let state = this._statesToRestore[aWindow.__SS_restoreID]; let state = this._statesToRestore[aWindow.__SS_restoreID];
let options = {overwriteTabs: true, isFollowUp: state.windows.length == 1}; let options = {overwriteTabs: true, isFollowUp: state.windows.length == 1};
this.restoreWindow(aWindow, state.windows[0], options); this.restoreWindow(aWindow, state.windows[0], options);
}
// The user opened another, non-private window after starting up with // The user opened another, non-private window after starting up with
// a single private one. Let's restore the session we actually wanted to // a single private one. Let's restore the session we actually wanted to
// restore at startup. // restore at startup.
else if (this._deferredInitialState && !isPrivateWindow && } else if (this._deferredInitialState && !isPrivateWindow &&
aWindow.toolbar.visible) { aWindow.toolbar.visible) {
// global data must be restored before restoreWindow is called so that // global data must be restored before restoreWindow is called so that
@ -1165,8 +1160,7 @@ var SessionStoreInternal = {
this._deferredInitialState.windows.length : 0; this._deferredInitialState.windows.length : 0;
this.restoreWindows(aWindow, this._deferredInitialState, {firstWindow: true}); this.restoreWindows(aWindow, this._deferredInitialState, {firstWindow: true});
this._deferredInitialState = null; this._deferredInitialState = null;
} } else if (this._restoreLastWindow && aWindow.toolbar.visible &&
else if (this._restoreLastWindow && aWindow.toolbar.visible &&
this._closedWindows.length && !isPrivateWindow) { this._closedWindows.length && !isPrivateWindow) {
// default to the most-recently closed window // default to the most-recently closed window
@ -1202,14 +1196,12 @@ var SessionStoreInternal = {
// In case there were no unpinned tabs, remove the window from _closedWindows // In case there were no unpinned tabs, remove the window from _closedWindows
if (!normalTabsState.windows.length) { if (!normalTabsState.windows.length) {
this._removeClosedWindow(closedWindowIndex); this._removeClosedWindow(closedWindowIndex);
}
// Or update _closedWindows with the modified state // Or update _closedWindows with the modified state
else { } else {
delete normalTabsState.windows[0].__lastSessionWindowID; delete normalTabsState.windows[0].__lastSessionWindowID;
this._closedWindows[closedWindowIndex] = normalTabsState.windows[0]; this._closedWindows[closedWindowIndex] = normalTabsState.windows[0];
} }
} } else {
else {
// If we're just restoring the window, make sure it gets removed from // If we're just restoring the window, make sure it gets removed from
// _closedWindows. // _closedWindows.
this._removeClosedWindow(closedWindowIndex); this._removeClosedWindow(closedWindowIndex);
@ -1241,7 +1233,7 @@ var SessionStoreInternal = {
* @param aWindow * @param aWindow
* Window reference * Window reference
*/ */
onBeforeBrowserWindowShown: function (aWindow) { onBeforeBrowserWindowShown(aWindow) {
// Register the window. // Register the window.
this.onLoad(aWindow); this.onLoad(aWindow);
@ -1547,7 +1539,7 @@ var SessionStoreInternal = {
/** /**
* On quit application granted * On quit application granted
*/ */
onQuitApplicationGranted: function ssi_onQuitApplicationGranted(syncShutdown=false) { onQuitApplicationGranted: function ssi_onQuitApplicationGranted(syncShutdown = false) {
// Collect an initial snapshot of window data before we do the flush // Collect an initial snapshot of window data before we do the flush
this._forEachBrowserWindow((win) => { this._forEachBrowserWindow((win) => {
this._collectWindowData(win); this._collectWindowData(win);
@ -1623,7 +1615,7 @@ var SessionStoreInternal = {
* *
* @return Promise * @return Promise
*/ */
flushAllWindowsAsync: Task.async(function*(progress={}) { flushAllWindowsAsync: Task.async(function*(progress = {}) {
let windowPromises = new Map(); let windowPromises = new Map();
// We collect flush promises and close each window immediately so that // We collect flush promises and close each window immediately so that
// the user can't start changing any window state while we're waiting // the user can't start changing any window state while we're waiting
@ -1651,7 +1643,7 @@ var SessionStoreInternal = {
yield promise; yield promise;
this._collectWindowData(win); this._collectWindowData(win);
progress.current++; progress.current++;
}; }
// We must cache this because _getMostRecentBrowserWindow will always // We must cache this because _getMostRecentBrowserWindow will always
// return null by the time quit-application occurs. // return null by the time quit-application occurs.
@ -1782,8 +1774,7 @@ var SessionStoreInternal = {
} }
if (openTabs.length == 0) { if (openTabs.length == 0) {
this._closedWindows.splice(ix, 1); this._closedWindows.splice(ix, 1);
} } else if (openTabs.length != openTabCount) {
else if (openTabs.length != openTabCount) {
// Adjust the window's title if we removed an open tab // Adjust the window's title if we removed an open tab
let selectedTab = openTabs[this._closedWindows[ix].selected - 1]; let selectedTab = openTabs[this._closedWindows[ix].selected - 1];
// some duplication from restoreHistory - make sure we get the correct title // some duplication from restoreHistory - make sure we get the correct title
@ -2078,7 +2069,7 @@ var SessionStoreInternal = {
* @param aBrowser * @param aBrowser
* The <xul:browser> that is now in the crashed state. * The <xul:browser> that is now in the crashed state.
*/ */
onBrowserCrashed: function(aBrowser) { onBrowserCrashed(aBrowser) {
NS_ASSERT(aBrowser.isRemoteBrowser, NS_ASSERT(aBrowser.isRemoteBrowser,
"Only remote browsers should be able to crash"); "Only remote browsers should be able to crash");
@ -2114,7 +2105,7 @@ var SessionStoreInternal = {
// Clean up data that has been closed a long time ago. // Clean up data that has been closed a long time ago.
// Do not reschedule a save. This will wait for the next regular // Do not reschedule a save. This will wait for the next regular
// save. // save.
onIdleDaily: function() { onIdleDaily() {
// Remove old closed windows // Remove old closed windows
this._cleanupOldData([this._closedWindows]); this._cleanupOldData([this._closedWindows]);
@ -2128,12 +2119,12 @@ var SessionStoreInternal = {
}, },
// Remove "old" data from an array // Remove "old" data from an array
_cleanupOldData: function(targets) { _cleanupOldData(targets) {
const TIME_TO_LIVE = this._prefBranch.getIntPref("sessionstore.cleanup.forget_closed_after"); const TIME_TO_LIVE = this._prefBranch.getIntPref("sessionstore.cleanup.forget_closed_after");
const now = Date.now(); const now = Date.now();
for (let array of targets) { for (let array of targets) {
for (let i = array.length - 1; i >= 0; --i) { for (let i = array.length - 1; i >= 0; --i) {
let data = array[i]; let data = array[i];
// Make sure that we have a timestamp to tell us when the target // Make sure that we have a timestamp to tell us when the target
// has been closed. If we don't have a timestamp, default to a // has been closed. If we don't have a timestamp, default to a
@ -2166,8 +2157,7 @@ var SessionStoreInternal = {
try { try {
var state = JSON.parse(aState); var state = JSON.parse(aState);
} } catch (ex) { /* invalid state object - don't restore anything */ }
catch (ex) { /* invalid state object - don't restore anything */ }
if (!state) { if (!state) {
throw Components.Exception("Invalid state string: not JSON", Cr.NS_ERROR_INVALID_ARG); throw Components.Exception("Invalid state string: not JSON", Cr.NS_ERROR_INVALID_ARG);
} }
@ -2462,7 +2452,7 @@ var SessionStoreInternal = {
getWindowValue: function ssi_getWindowValue(aWindow, aKey) { getWindowValue: function ssi_getWindowValue(aWindow, aKey) {
if ("__SSi" in aWindow) { if ("__SSi" in aWindow) {
var data = this._windows[aWindow.__SSi].extData || {}; let data = this._windows[aWindow.__SSi].extData || {};
return data[aKey] || ""; return data[aKey] || "";
} }
@ -2658,12 +2648,11 @@ var SessionStoreInternal = {
// Restore into that window - pretend it's a followup since we'll already // Restore into that window - pretend it's a followup since we'll already
// have a focused window. // have a focused window.
//XXXzpao This is going to merge extData together (taking what was in // XXXzpao This is going to merge extData together (taking what was in
// winState over what is in the window already. // winState over what is in the window already.
let options = {overwriteTabs: canOverwriteTabs, isFollowUp: true}; let options = {overwriteTabs: canOverwriteTabs, isFollowUp: true};
this.restoreWindow(windowToUse, winState, options); this.restoreWindow(windowToUse, winState, options);
} } else {
else {
this._openWindowWithState({ windows: [winState] }); this._openWindowWithState({ windows: [winState] });
} }
} }
@ -2794,10 +2783,10 @@ var SessionStoreInternal = {
return; return;
} }
let window = tab.ownerGlobal; let refreshedWindow = tab.ownerGlobal;
// The tab or its window might be gone. // The tab or its window might be gone.
if (!window || !window.__SSi || window.closed) { if (!refreshedWindow || !refreshedWindow.__SSi || refreshedWindow.closed) {
return; return;
} }
@ -2858,6 +2847,7 @@ var SessionStoreInternal = {
let tabState = TabState.collect(tab); let tabState = TabState.collect(tab);
return { index: tabState.index - 1, entries: tabState.entries } return { index: tabState.index - 1, entries: tabState.entries }
} }
return null;
}, },
/** /**
@ -2886,7 +2876,6 @@ var SessionStoreInternal = {
let homePages = ["about:blank"]; let homePages = ["about:blank"];
let removableTabs = []; let removableTabs = [];
let tabbrowser = aWindow.gBrowser; let tabbrowser = aWindow.gBrowser;
let normalTabsLen = tabbrowser.tabs.length - tabbrowser._numPinnedTabs;
let startupPref = this._prefBranch.getIntPref("startup.page"); let startupPref = this._prefBranch.getIntPref("startup.page");
if (startupPref == 1) if (startupPref == 1)
homePages = homePages.concat(aWindow.gHomeButton.getHomePage().split("|")); homePages = homePages.concat(aWindow.gHomeButton.getHomePage().split("|"));
@ -2900,8 +2889,7 @@ var SessionStoreInternal = {
if (tabbrowser.tabs.length == removableTabs.length) { if (tabbrowser.tabs.length == removableTabs.length) {
canOverwriteTabs = true; canOverwriteTabs = true;
} } else {
else {
// If we're not overwriting all of the tabs, then close the home tabs. // If we're not overwriting all of the tabs, then close the home tabs.
for (let i = removableTabs.length - 1; i >= 0; i--) { for (let i = removableTabs.length - 1; i >= 0; i--) {
tabbrowser.removeTab(removableTabs.pop(), { animate: false }); tabbrowser.removeTab(removableTabs.pop(), { animate: false });
@ -2946,7 +2934,7 @@ var SessionStoreInternal = {
* Bool update all windows * Bool update all windows
* @returns object * @returns object
*/ */
getCurrentState: function (aUpdateAll) { getCurrentState(aUpdateAll) {
this._handleClosedWindows().then(() => { this._handleClosedWindows().then(() => {
this._notifyOfClosedObjectsChange(); this._notifyOfClosedObjectsChange();
}); });
@ -2961,8 +2949,7 @@ var SessionStoreInternal = {
return; return;
if (aUpdateAll || DirtyWindows.has(aWindow) || aWindow == activeWindow) { if (aUpdateAll || DirtyWindows.has(aWindow) || aWindow == activeWindow) {
this._collectWindowData(aWindow); this._collectWindowData(aWindow);
} } else { // always update the window features (whose change alone never triggers a save operation)
else { // always update the window features (whose change alone never triggers a save operation)
this._updateWindowFeatures(aWindow); this._updateWindowFeatures(aWindow);
} }
}); });
@ -3008,7 +2995,7 @@ var SessionStoreInternal = {
// If no non-popup browser window remains open, return the state of the last // If no non-popup browser window remains open, return the state of the last
// closed window(s). We only want to do this when we're actually "ending" // closed window(s). We only want to do this when we're actually "ending"
// the session. // the session.
//XXXzpao We should do this for _restoreLastWindow == true, but that has // XXXzpao We should do this for _restoreLastWindow == true, but that has
// its own check for popups. c.f. bug 597619 // its own check for popups. c.f. bug 597619
if (nonPopupCount == 0 && lastClosedWindowsCopy.length > 0 && if (nonPopupCount == 0 && lastClosedWindowsCopy.length > 0 &&
RunState.isQuitting) { RunState.isQuitting) {
@ -3040,7 +3027,7 @@ var SessionStoreInternal = {
windows: total, windows: total,
selectedWindow: ix + 1, selectedWindow: ix + 1,
_closedWindows: lastClosedWindowsCopy, _closedWindows: lastClosedWindowsCopy,
session: session, session,
global: this._globalState.getState() global: this._globalState.getState()
}; };
@ -3084,7 +3071,7 @@ var SessionStoreInternal = {
let windows = [this._windows[aWindow.__SSi]]; let windows = [this._windows[aWindow.__SSi]];
SessionCookies.update(windows); SessionCookies.update(windows);
return { windows: windows }; return { windows };
}, },
/** /**
@ -3163,11 +3150,9 @@ var SessionStoreInternal = {
if (!winData.tabs) { if (!winData.tabs) {
winData.tabs = []; winData.tabs = [];
}
// don't restore a single blank tab when we've had an external // don't restore a single blank tab when we've had an external
// URL passed in for loading at startup (cf. bug 357419) // URL passed in for loading at startup (cf. bug 357419)
else if (firstWindow && !overwriteTabs && winData.tabs.length == 1 && } else if (firstWindow && !overwriteTabs && winData.tabs.length == 1 &&
(!winData.tabs[0].entries || winData.tabs[0].entries.length == 0)) { (!winData.tabs[0].entries || winData.tabs[0].entries.length == 0)) {
winData.tabs = []; winData.tabs = [];
} }
@ -3233,8 +3218,7 @@ var SessionStoreInternal = {
if (winData.tabs[t].hidden) { if (winData.tabs[t].hidden) {
tabbrowser.hideTab(tabs[t]); tabbrowser.hideTab(tabs[t]);
} } else {
else {
tabbrowser.showTab(tabs[t]); tabbrowser.showTab(tabs[t]);
numVisibleTabs++; numVisibleTabs++;
} }
@ -3366,8 +3350,7 @@ var SessionStoreInternal = {
let root; let root;
try { try {
root = (typeof aState == "string") ? JSON.parse(aState) : aState; root = (typeof aState == "string") ? JSON.parse(aState) : aState;
} } catch (ex) { // invalid state object - don't restore anything
catch (ex) { // invalid state object - don't restore anything
debug(ex); debug(ex);
this._sendRestoreCompletedNotifications(); this._sendRestoreCompletedNotifications();
return; return;
@ -3589,7 +3572,7 @@ var SessionStoreInternal = {
}); });
browser.messageManager.sendAsyncMessage("SessionStore:restoreHistory", browser.messageManager.sendAsyncMessage("SessionStore:restoreHistory",
{tabData: tabData, epoch: epoch, loadArguments}); {tabData, epoch, loadArguments});
// Restore tab attributes. // Restore tab attributes.
if ("attributes" in tabData) { if ("attributes" in tabData) {
@ -3618,7 +3601,7 @@ var SessionStoreInternal = {
* @param aReloadInFreshProcess * @param aReloadInFreshProcess
* true if we want to reload into a fresh process * true if we want to reload into a fresh process
*/ */
restoreTabContent: function (aTab, aLoadArguments = null, aReloadInFreshProcess = false) { restoreTabContent(aTab, aLoadArguments = null, aReloadInFreshProcess = false) {
if (aTab.hasAttribute("customizemode") && !aLoadArguments) { if (aTab.hasAttribute("customizemode") && !aLoadArguments) {
return; return;
} }
@ -3651,7 +3634,7 @@ var SessionStoreInternal = {
let isRemotenessUpdate = let isRemotenessUpdate =
tabbrowser.updateBrowserRemotenessByURL(browser, uri, { tabbrowser.updateBrowserRemotenessByURL(browser, uri, {
freshProcess: aReloadInFreshProcess, freshProcess: aReloadInFreshProcess,
newFrameloader: newFrameloader, newFrameloader,
}); });
if (isRemotenessUpdate) { if (isRemotenessUpdate) {
@ -3663,8 +3646,8 @@ var SessionStoreInternal = {
let epoch = this.startNextEpoch(browser); let epoch = this.startNextEpoch(browser);
browser.messageManager.sendAsyncMessage("SessionStore:restoreHistory", { browser.messageManager.sendAsyncMessage("SessionStore:restoreHistory", {
tabData: tabData, tabData,
epoch: epoch, epoch,
loadArguments: aLoadArguments, loadArguments: aLoadArguments,
isRemotenessUpdate, isRemotenessUpdate,
}); });
@ -3736,7 +3719,7 @@ var SessionStoreInternal = {
* Object containing session data for the window * Object containing session data for the window
*/ */
restoreWindowFeatures: function ssi_restoreWindowFeatures(aWindow, aWinData) { restoreWindowFeatures: function ssi_restoreWindowFeatures(aWindow, aWinData) {
var hidden = (aWinData.hidden)?aWinData.hidden.split(","):[]; var hidden = (aWinData.hidden) ? aWinData.hidden.split(",") : [];
WINDOW_HIDEABLE_FEATURES.forEach(function(aItem) { WINDOW_HIDEABLE_FEATURES.forEach(function(aItem) {
aWindow[aItem].visible = hidden.indexOf(aItem) == -1; aWindow[aItem].visible = hidden.indexOf(aItem) == -1;
}); });
@ -3747,8 +3730,7 @@ var SessionStoreInternal = {
aWindow.gURLBar.readOnly = true; aWindow.gURLBar.readOnly = true;
aWindow.gURLBar.setAttribute("enablehistory", "false"); aWindow.gURLBar.setAttribute("enablehistory", "false");
} }
} } else {
else {
delete this._windows[aWindow.__SSi].isPopup; delete this._windows[aWindow.__SSi].isPopup;
if (aWindow.gURLBar) { if (aWindow.gURLBar) {
aWindow.gURLBar.readOnly = false; aWindow.gURLBar.readOnly = false;
@ -3756,14 +3738,13 @@ var SessionStoreInternal = {
} }
} }
var _this = this; aWindow.setTimeout(() => {
aWindow.setTimeout(function() { this.restoreDimensions(aWindow,
_this.restoreDimensions.apply(_this, [aWindow,
+(aWinData.width || 0), +(aWinData.width || 0),
+(aWinData.height || 0), +(aWinData.height || 0),
"screenX" in aWinData ? +aWinData.screenX : NaN, "screenX" in aWinData ? +aWinData.screenX : NaN,
"screenY" in aWinData ? +aWinData.screenY : NaN, "screenY" in aWinData ? +aWinData.screenY : NaN,
aWinData.sizemode || "", aWinData.sidebar || ""]); aWinData.sizemode || "", aWinData.sidebar || "");
}, 0); }, 0);
}, },
@ -3845,10 +3826,8 @@ var SessionStoreInternal = {
aWindow.resizeTo(aWidth, aHeight); aWindow.resizeTo(aWidth, aHeight);
} }
} }
if (aSizeMode && win_("sizemode") != aSizeMode) if (aSizeMode && win_("sizemode") != aSizeMode) {
{ switch (aSizeMode) {
switch (aSizeMode)
{
case "maximized": case "maximized":
aWindow.maximize(); aWindow.maximize();
break; break;
@ -3880,7 +3859,7 @@ var SessionStoreInternal = {
* Will mark the given window as dirty so that we will recollect its * Will mark the given window as dirty so that we will recollect its
* data before we start writing. * data before we start writing.
*/ */
saveStateDelayed: function (aWindow = null) { saveStateDelayed(aWindow = null) {
if (aWindow) { if (aWindow) {
DirtyWindows.add(aWindow); DirtyWindows.add(aWindow);
} }
@ -4172,7 +4151,7 @@ var SessionStoreInternal = {
* @param aURL is the single URL we're looking for * @param aURL is the single URL we're looking for
* @returns whether the window data contains only the single URL passed * @returns whether the window data contains only the single URL passed
*/ */
_hasSingleTabWithURL: function(aWinData, aURL) { _hasSingleTabWithURL(aWinData, aURL) {
if (aWinData && if (aWinData &&
aWinData.length == 1 && aWinData.length == 1 &&
aWinData[0].tabs && aWinData[0].tabs &&
@ -4539,7 +4518,7 @@ var SessionStoreInternal = {
* @param aTab * @param aTab
* The tab that will be "reset" * The tab that will be "reset"
*/ */
_resetLocalTabRestoringState: function (aTab) { _resetLocalTabRestoringState(aTab) {
NS_ASSERT(aTab.linkedBrowser.__SS_restoreState, NS_ASSERT(aTab.linkedBrowser.__SS_restoreState,
"given tab is not restoring"); "given tab is not restoring");
@ -4565,7 +4544,7 @@ var SessionStoreInternal = {
} }
}, },
_resetTabRestoringState: function (tab) { _resetTabRestoringState(tab) {
NS_ASSERT(tab.linkedBrowser.__SS_restoreState, NS_ASSERT(tab.linkedBrowser.__SS_restoreState,
"given tab is not restoring"); "given tab is not restoring");
@ -4609,7 +4588,7 @@ var SessionStoreInternal = {
* epoch. This function does that, and returns true if |epoch| is up-to-date * epoch. This function does that, and returns true if |epoch| is up-to-date
* with respect to |browser|. * with respect to |browser|.
*/ */
isCurrentEpoch: function (browser, epoch) { isCurrentEpoch(browser, epoch) {
return this.getCurrentEpoch(browser) == epoch; return this.getCurrentEpoch(browser) == epoch;
}, },
@ -4680,7 +4659,7 @@ var TabRestoreQueue = {
get restoreOnDemand() { get restoreOnDemand() {
let updateValue = () => { let updateValue = () => {
let value = Services.prefs.getBoolPref(PREF); let value = Services.prefs.getBoolPref(PREF);
let definition = {value: value, configurable: true}; let definition = {value, configurable: true};
Object.defineProperty(this, "restoreOnDemand", definition); Object.defineProperty(this, "restoreOnDemand", definition);
return value; return value;
} }
@ -4694,7 +4673,7 @@ var TabRestoreQueue = {
get restorePinnedTabsOnDemand() { get restorePinnedTabsOnDemand() {
let updateValue = () => { let updateValue = () => {
let value = Services.prefs.getBoolPref(PREF); let value = Services.prefs.getBoolPref(PREF);
let definition = {value: value, configurable: true}; let definition = {value, configurable: true};
Object.defineProperty(this, "restorePinnedTabsOnDemand", definition); Object.defineProperty(this, "restorePinnedTabsOnDemand", definition);
return value; return value;
} }
@ -4708,7 +4687,7 @@ var TabRestoreQueue = {
get restoreHiddenTabs() { get restoreHiddenTabs() {
let updateValue = () => { let updateValue = () => {
let value = Services.prefs.getBoolPref(PREF); let value = Services.prefs.getBoolPref(PREF);
let definition = {value: value, configurable: true}; let definition = {value, configurable: true};
Object.defineProperty(this, "restoreHiddenTabs", definition); Object.defineProperty(this, "restoreHiddenTabs", definition);
return value; return value;
} }
@ -4720,12 +4699,12 @@ var TabRestoreQueue = {
}, },
// Resets the queue and removes all tabs. // Resets the queue and removes all tabs.
reset: function () { reset() {
this.tabs = {priority: [], visible: [], hidden: []}; this.tabs = {priority: [], visible: [], hidden: []};
}, },
// Adds a tab to the queue and determines its priority bucket. // Adds a tab to the queue and determines its priority bucket.
add: function (tab) { add(tab) {
let {priority, hidden, visible} = this.tabs; let {priority, hidden, visible} = this.tabs;
if (tab.pinned) { if (tab.pinned) {
@ -4738,7 +4717,7 @@ var TabRestoreQueue = {
}, },
// Removes a given tab from the queue, if it's in there. // Removes a given tab from the queue, if it's in there.
remove: function (tab) { remove(tab) {
let {priority, hidden, visible} = this.tabs; let {priority, hidden, visible} = this.tabs;
// We'll always check priority first since we don't // We'll always check priority first since we don't
@ -4757,7 +4736,7 @@ var TabRestoreQueue = {
}, },
// Returns and removes the tab with the highest priority. // Returns and removes the tab with the highest priority.
shift: function () { shift() {
let set; let set;
let {priority, hidden, visible} = this.tabs; let {priority, hidden, visible} = this.tabs;
@ -4777,7 +4756,7 @@ var TabRestoreQueue = {
}, },
// Moves a given tab from the 'hidden' to the 'visible' bucket. // Moves a given tab from the 'hidden' to the 'visible' bucket.
hiddenToVisible: function (tab) { hiddenToVisible(tab) {
let {hidden, visible} = this.tabs; let {hidden, visible} = this.tabs;
let index = hidden.indexOf(tab); let index = hidden.indexOf(tab);
@ -4788,7 +4767,7 @@ var TabRestoreQueue = {
}, },
// Moves a given tab from the 'visible' to the 'hidden' bucket. // Moves a given tab from the 'visible' to the 'hidden' bucket.
visibleToHidden: function (tab) { visibleToHidden(tab) {
let {visible, hidden} = this.tabs; let {visible, hidden} = this.tabs;
let index = visible.indexOf(tab); let index = visible.indexOf(tab);
@ -4806,7 +4785,7 @@ var TabRestoreQueue = {
* The tab to check * The tab to check
* @returns bool * @returns bool
*/ */
willRestoreSoon: function (tab) { willRestoreSoon(tab) {
let { priority, hidden, visible } = this.tabs; let { priority, hidden, visible } = this.tabs;
let { restoreOnDemand, restorePinnedTabsOnDemand, let { restoreOnDemand, restorePinnedTabsOnDemand,
restoreHiddenTabs } = this.prefs; restoreHiddenTabs } = this.prefs;
@ -4834,19 +4813,19 @@ var TabRestoreQueue = {
var DyingWindowCache = { var DyingWindowCache = {
_data: new WeakMap(), _data: new WeakMap(),
has: function (window) { has(window) {
return this._data.has(window); return this._data.has(window);
}, },
get: function (window) { get(window) {
return this._data.get(window); return this._data.get(window);
}, },
set: function (window, data) { set(window, data) {
this._data.set(window, data); this._data.set(window, data);
}, },
remove: function (window) { remove(window) {
this._data.delete(window); this._data.delete(window);
} }
}; };
@ -4856,19 +4835,19 @@ var DyingWindowCache = {
var DirtyWindows = { var DirtyWindows = {
_data: new WeakMap(), _data: new WeakMap(),
has: function (window) { has(window) {
return this._data.has(window); return this._data.has(window);
}, },
add: function (window) { add(window) {
return this._data.set(window, true); return this._data.set(window, true);
}, },
remove: function (window) { remove(window) {
this._data.delete(window); this._data.delete(window);
}, },
clear: function (window) { clear(window) {
this._data = new WeakMap(); this._data = new WeakMap();
} }
}; };
@ -4884,15 +4863,15 @@ var LastSession = {
return !!this._state; return !!this._state;
}, },
getState: function () { getState() {
return this._state; return this._state;
}, },
setState: function (state) { setState(state) {
this._state = state; this._state = state;
}, },
clear: function () { clear() {
if (this._state) { if (this._state) {
this._state = null; this._state = null;
Services.obs.notifyObservers(null, NOTIFY_LAST_SESSION_CLEARED, null); Services.obs.notifyObservers(null, NOTIFY_LAST_SESSION_CLEARED, null);

View File

@ -2,6 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file, * 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/. */ * You can obtain one at http://mozilla.org/MPL/2.0/. */
/* eslint-env worker */
/** /**
* A worker dedicated to handle I/O for Session Store. * A worker dedicated to handle I/O for Session Store.
*/ */
@ -124,7 +126,7 @@ var Agent = {
* - isFinalWrite If |true|, write to Paths.clean instead of * - isFinalWrite If |true|, write to Paths.clean instead of
* Paths.recovery * Paths.recovery
*/ */
write: function (state, options = {}) { write(state, options = {}) {
let exn; let exn;
let telemetry = {}; let telemetry = {};
@ -227,7 +229,7 @@ var Agent = {
try { try {
iterator = new File.DirectoryIterator(this.Paths.backups); iterator = new File.DirectoryIterator(this.Paths.backups);
iterator.forEach(function (file) { iterator.forEach(function(file) {
if (file.path.startsWith(upgradeBackupPrefix)) { if (file.path.startsWith(upgradeBackupPrefix)) {
backups.push(file.path); backups.push(file.path);
} }
@ -276,14 +278,14 @@ var Agent = {
result: { result: {
upgradeBackup: upgradeBackupComplete upgradeBackup: upgradeBackupComplete
}, },
telemetry: telemetry, telemetry,
}; };
}, },
/** /**
* Wipes all files holding session data from disk. * Wipes all files holding session data from disk.
*/ */
wipe: function () { wipe() {
// Don't stop immediately in case of error. // Don't stop immediately in case of error.
let exn = null; let exn = null;
@ -332,7 +334,7 @@ var Agent = {
* @param {string|null} prefix If provided, only remove files whose * @param {string|null} prefix If provided, only remove files whose
* name starts with a specific prefix. * name starts with a specific prefix.
*/ */
_wipeFromDir: function(path, prefix) { _wipeFromDir(path, prefix) {
// Sanity check // Sanity check
if (typeof prefix == "undefined" || prefix == "") { if (typeof prefix == "undefined" || prefix == "") {
throw new TypeError(); throw new TypeError();

View File

@ -57,7 +57,7 @@ this.StartupPerformance = {
_totalNumberOfTabs: 0, _totalNumberOfTabs: 0,
_totalNumberOfWindows: 0, _totalNumberOfWindows: 0,
init: function() { init() {
for (let topic of OBSERVED_TOPICS) { for (let topic of OBSERVED_TOPICS) {
Services.obs.addObserver(this, topic, false); Services.obs.addObserver(this, topic, false);
} }
@ -83,7 +83,7 @@ this.StartupPerformance = {
// Called when restoration starts. // Called when restoration starts.
// Record the start timestamp, setup the timer and `this._promiseFinished`. // Record the start timestamp, setup the timer and `this._promiseFinished`.
// Behavior is unspecified if there was already an ongoing measure. // Behavior is unspecified if there was already an ongoing measure.
_onRestorationStarts: function(isAutoRestore) { _onRestorationStarts(isAutoRestore) {
this._latestRestoredTimeStamp = this._startTimeStamp = Date.now(); this._latestRestoredTimeStamp = this._startTimeStamp = Date.now();
this._totalNumberOfEagerTabs = 0; this._totalNumberOfEagerTabs = 0;
this._totalNumberOfTabs = 0; this._totalNumberOfTabs = 0;
@ -131,7 +131,7 @@ this.StartupPerformance = {
}); });
}, },
_startTimer: function() { _startTimer() {
if (this._hasFired) { if (this._hasFired) {
return; return;
} }
@ -153,7 +153,7 @@ this.StartupPerformance = {
}, COLLECT_RESULTS_AFTER_MS); }, COLLECT_RESULTS_AFTER_MS);
}, },
observe: function(subject, topic, details) { observe(subject, topic, details) {
try { try {
switch (topic) { switch (topic) {
case "sessionstore-restoring-on-startup": case "sessionstore-restoring-on-startup":

View File

@ -20,15 +20,15 @@ const ATTRIBUTES_TO_SKIP = new Set(["image", "muted", "pending", "iconLoadingPri
// attributes when collecting tab data and will re-set those attributes when // attributes when collecting tab data and will re-set those attributes when
// the given tab data is restored to a new tab. // the given tab data is restored to a new tab.
this.TabAttributes = Object.freeze({ this.TabAttributes = Object.freeze({
persist: function (name) { persist(name) {
return TabAttributesInternal.persist(name); return TabAttributesInternal.persist(name);
}, },
get: function (tab) { get(tab) {
return TabAttributesInternal.get(tab); return TabAttributesInternal.get(tab);
}, },
set: function (tab, data = {}) { set(tab, data = {}) {
TabAttributesInternal.set(tab, data); TabAttributesInternal.set(tab, data);
} }
}); });
@ -36,7 +36,7 @@ this.TabAttributes = Object.freeze({
var TabAttributesInternal = { var TabAttributesInternal = {
_attrs: new Set(), _attrs: new Set(),
persist: function (name) { persist(name) {
if (this._attrs.has(name) || ATTRIBUTES_TO_SKIP.has(name)) { if (this._attrs.has(name) || ATTRIBUTES_TO_SKIP.has(name)) {
return false; return false;
} }
@ -45,7 +45,7 @@ var TabAttributesInternal = {
return true; return true;
}, },
get: function (tab) { get(tab) {
let data = {}; let data = {};
for (let name of this._attrs) { for (let name of this._attrs) {
@ -57,7 +57,7 @@ var TabAttributesInternal = {
return data; return data;
}, },
set: function (tab, data = {}) { set(tab, data = {}) {
// Clear attributes. // Clear attributes.
for (let name of this._attrs) { for (let name of this._attrs) {
tab.removeAttribute(name); tab.removeAttribute(name);

View File

@ -23,15 +23,15 @@ XPCOMUtils.defineLazyModuleGetter(this, "Utils",
* Module that contains tab state collection methods. * Module that contains tab state collection methods.
*/ */
this.TabState = Object.freeze({ this.TabState = Object.freeze({
update: function (browser, data) { update(browser, data) {
TabStateInternal.update(browser, data); TabStateInternal.update(browser, data);
}, },
collect: function (tab) { collect(tab) {
return TabStateInternal.collect(tab); return TabStateInternal.collect(tab);
}, },
clone: function (tab) { clone(tab) {
return TabStateInternal.clone(tab); return TabStateInternal.clone(tab);
}, },
@ -44,7 +44,7 @@ var TabStateInternal = {
/** /**
* Processes a data update sent by the content script. * Processes a data update sent by the content script.
*/ */
update: function (browser, {data}) { update(browser, {data}) {
TabStateCache.update(browser, data); TabStateCache.update(browser, data);
}, },
@ -58,7 +58,7 @@ var TabStateInternal = {
* tab has not been invalidated since the last call to * tab has not been invalidated since the last call to
* collect(aTab), the same object is returned. * collect(aTab), the same object is returned.
*/ */
collect: function (tab) { collect(tab) {
return this._collectBaseTabData(tab); return this._collectBaseTabData(tab);
}, },
@ -73,7 +73,7 @@ var TabStateInternal = {
* cached, it will always be read from the tab and thus be * cached, it will always be read from the tab and thus be
* up-to-date. * up-to-date.
*/ */
clone: function (tab) { clone(tab) {
return this._collectBaseTabData(tab, {includePrivateData: true}); return this._collectBaseTabData(tab, {includePrivateData: true});
}, },
@ -87,7 +87,7 @@ var TabStateInternal = {
* *
* @returns {object} An object with the basic data for this tab. * @returns {object} An object with the basic data for this tab.
*/ */
_collectBaseTabData: function (tab, options) { _collectBaseTabData(tab, options) {
let tabData = { entries: [], lastAccessed: tab.lastAccessed }; let tabData = { entries: [], lastAccessed: tab.lastAccessed };
let browser = tab.linkedBrowser; let browser = tab.linkedBrowser;
@ -164,7 +164,6 @@ var TabStateInternal = {
// The caller may explicitly request to omit privacy checks. // The caller may explicitly request to omit privacy checks.
let includePrivateData = options && options.includePrivateData; let includePrivateData = options && options.includePrivateData;
let isPinned = !!tabData.pinned;
for (let key of Object.keys(data)) { for (let key of Object.keys(data)) {
let value = data[key]; let value = data[key];

View File

@ -26,7 +26,7 @@ this.TabStateCache = Object.freeze({
* The cached data stored for the given |tab| * The cached data stored for the given |tab|
* or associated |browser|. * or associated |browser|.
*/ */
get: function (browserOrTab) { get(browserOrTab) {
return TabStateCacheInternal.get(browserOrTab); return TabStateCacheInternal.get(browserOrTab);
}, },
@ -39,7 +39,7 @@ this.TabStateCache = Object.freeze({
* The new data to be stored for the given |tab| * The new data to be stored for the given |tab|
* or associated |browser|. * or associated |browser|.
*/ */
update: function (browserOrTab, newData) { update(browserOrTab, newData) {
TabStateCacheInternal.update(browserOrTab, newData); TabStateCacheInternal.update(browserOrTab, newData);
} }
}); });
@ -56,7 +56,7 @@ var TabStateCacheInternal = {
* The cached data stored for the given |tab| * The cached data stored for the given |tab|
* or associated |browser|. * or associated |browser|.
*/ */
get: function (browserOrTab) { get(browserOrTab) {
return this._data.get(browserOrTab.permanentKey); return this._data.get(browserOrTab.permanentKey);
}, },
@ -70,7 +70,7 @@ var TabStateCacheInternal = {
* @param change (object) * @param change (object)
* The actual changed values per domain. * The actual changed values per domain.
*/ */
updatePartialStorageChange: function (data, change) { updatePartialStorageChange(data, change) {
if (!data.storage) { if (!data.storage) {
data.storage = {}; data.storage = {};
} }
@ -105,7 +105,7 @@ var TabStateCacheInternal = {
* Object containing the tail of the history array, and * Object containing the tail of the history array, and
* some additional metadata. * some additional metadata.
*/ */
updatePartialHistoryChange: function (data, change) { updatePartialHistoryChange(data, change) {
const kLastIndex = Number.MAX_SAFE_INTEGER - 1; const kLastIndex = Number.MAX_SAFE_INTEGER - 1;
if (!data.history) { if (!data.history) {
@ -140,7 +140,7 @@ var TabStateCacheInternal = {
* The new data to be stored for the given |tab| * The new data to be stored for the given |tab|
* or associated |browser|. * or associated |browser|.
*/ */
update: function (browserOrTab, newData) { update(browserOrTab, newData) {
let data = this._data.get(browserOrTab.permanentKey) || {}; let data = this._data.get(browserOrTab.permanentKey) || {};
for (let key of Object.keys(newData)) { for (let key of Object.keys(newData)) {

View File

@ -48,7 +48,7 @@ this.TabStateFlusher = Object.freeze({
* An error message that will be sent to the Console in the * An error message that will be sent to the Console in the
* event that a flush failed. * event that a flush failed.
*/ */
resolve(browser, flushID, success=true, message="") { resolve(browser, flushID, success = true, message = "") {
TabStateFlusherInternal.resolve(browser, flushID, success, message); TabStateFlusherInternal.resolve(browser, flushID, success, message);
}, },
@ -66,7 +66,7 @@ this.TabStateFlusher = Object.freeze({
* An error message that will be sent to the Console in the * An error message that will be sent to the Console in the
* event that the flushes failed. * event that the flushes failed.
*/ */
resolveAll(browser, success=true, message="") { resolveAll(browser, success = true, message = "") {
TabStateFlusherInternal.resolveAll(browser, success, message); TabStateFlusherInternal.resolveAll(browser, success, message);
} }
}); });
@ -124,7 +124,7 @@ var TabStateFlusherInternal = {
* An error message that will be sent to the Console in the * An error message that will be sent to the Console in the
* event that a flush failed. * event that a flush failed.
*/ */
resolve(browser, flushID, success=true, message="") { resolve(browser, flushID, success = true, message = "") {
// Nothing to do if there are no pending flushes for the given browser. // Nothing to do if there are no pending flushes for the given browser.
if (!this._requests.has(browser.permanentKey)) { if (!this._requests.has(browser.permanentKey)) {
return; return;
@ -160,7 +160,7 @@ var TabStateFlusherInternal = {
* An error message that will be sent to the Console in the * An error message that will be sent to the Console in the
* event that the flushes failed. * event that the flushes failed.
*/ */
resolveAll(browser, success=true, message="") { resolveAll(browser, success = true, message = "") {
// Nothing to do if there are no pending flushes for the given browser. // Nothing to do if there are no pending flushes for the given browser.
if (!this._requests.has(browser.permanentKey)) { if (!this._requests.has(browser.permanentKey)) {
return; return;

View File

@ -194,15 +194,13 @@ function onListClick(aEvent) {
!treeView.isContainer(cell.row)) { !treeView.isContainer(cell.row)) {
restoreSingleTab(cell.row, aEvent.shiftKey); restoreSingleTab(cell.row, aEvent.shiftKey);
aEvent.stopPropagation(); aEvent.stopPropagation();
} } else if (cell.col.id == "restore")
else if (cell.col.id == "restore")
toggleRowChecked(cell.row); toggleRowChecked(cell.row);
} }
} }
function onListKeyDown(aEvent) { function onListKeyDown(aEvent) {
switch (aEvent.keyCode) switch (aEvent.keyCode) {
{
case KeyEvent.DOM_VK_SPACE: case KeyEvent.DOM_VK_SPACE:
toggleRowChecked(document.getElementById("tabList").currentIndex); toggleRowChecked(document.getElementById("tabList").currentIndex);
// Prevent page from scrolling on the space key. // Prevent page from scrolling on the space key.
@ -239,11 +237,16 @@ function toggleRowChecked(aIx) {
tab.checked = item.checked; tab.checked = item.checked;
treeView.treeBox.invalidateRow(gTreeData.indexOf(tab)); treeView.treeBox.invalidateRow(gTreeData.indexOf(tab));
} }
} } else {
else { // Update the window's checkmark as well (0 means "partially checked").
// update the window's checkmark as well (0 means "partially checked") let state = false;
item.parent.checked = item.parent.tabs.every(isChecked) ? true : if (item.parent.tabs.every(isChecked)) {
item.parent.tabs.some(isChecked) ? 0 : false; state = true;
} else if (item.parent.tabs.some(isChecked)) {
state = 0;
}
item.parent.checked = state;
treeView.treeBox.invalidateRow(gTreeData.indexOf(item.parent)); treeView.treeBox.invalidateRow(gTreeData.indexOf(item.parent));
} }
@ -277,20 +280,20 @@ var treeView = {
treeBox: null, treeBox: null,
selection: null, selection: null,
get rowCount() { return gTreeData.length; }, get rowCount() { return gTreeData.length; },
setTree: function(treeBox) { this.treeBox = treeBox; }, setTree(treeBox) { this.treeBox = treeBox; },
getCellText: function(idx, column) { return gTreeData[idx].label; }, getCellText(idx, column) { return gTreeData[idx].label; },
isContainer: function(idx) { return "open" in gTreeData[idx]; }, isContainer(idx) { return "open" in gTreeData[idx]; },
getCellValue: function(idx, column){ return gTreeData[idx].checked; }, getCellValue(idx, column) { return gTreeData[idx].checked; },
isContainerOpen: function(idx) { return gTreeData[idx].open; }, isContainerOpen(idx) { return gTreeData[idx].open; },
isContainerEmpty: function(idx) { return false; }, isContainerEmpty(idx) { return false; },
isSeparator: function(idx) { return false; }, isSeparator(idx) { return false; },
isSorted: function() { return false; }, isSorted() { return false; },
isEditable: function(idx, column) { return false; }, isEditable(idx, column) { return false; },
canDrop: function(idx, orientation, dt) { return false; }, canDrop(idx, orientation, dt) { return false; },
getLevel: function(idx) { return this.isContainer(idx) ? 0 : 1; }, getLevel(idx) { return this.isContainer(idx) ? 0 : 1; },
getParentIndex: function(idx) { getParentIndex(idx) {
if (!this.isContainer(idx)) if (!this.isContainer(idx))
for (var t = idx - 1; t >= 0 ; t--) for (var t = idx - 1; t >= 0 ; t--)
if (this.isContainer(t)) if (this.isContainer(t))
@ -298,7 +301,7 @@ var treeView = {
return -1; return -1;
}, },
hasNextSibling: function(idx, after) { hasNextSibling(idx, after) {
var thisLevel = this.getLevel(idx); var thisLevel = this.getLevel(idx);
for (var t = after + 1; t < gTreeData.length; t++) for (var t = after + 1; t < gTreeData.length; t++)
if (this.getLevel(t) <= thisLevel) if (this.getLevel(t) <= thisLevel)
@ -306,7 +309,7 @@ var treeView = {
return false; return false;
}, },
toggleOpenState: function(idx) { toggleOpenState(idx) {
if (!this.isContainer(idx)) if (!this.isContainer(idx))
return; return;
var item = gTreeData[idx]; var item = gTreeData[idx];
@ -317,8 +320,7 @@ var treeView = {
var deletecount = t - idx - 1; var deletecount = t - idx - 1;
gTreeData.splice(idx + 1, deletecount); gTreeData.splice(idx + 1, deletecount);
this.treeBox.rowCountChanged(idx + 1, -deletecount); this.treeBox.rowCountChanged(idx + 1, -deletecount);
} } else {
else {
// add this window's tab rows to the view // add this window's tab rows to the view
var toinsert = gTreeData[idx].tabs; var toinsert = gTreeData[idx].tabs;
for (var i = 0; i < toinsert.length; i++) for (var i = 0; i < toinsert.length; i++)
@ -329,7 +331,7 @@ var treeView = {
this.treeBox.invalidateRow(idx); this.treeBox.invalidateRow(idx);
}, },
getCellProperties: function(idx, column) { getCellProperties(idx, column) {
if (column.id == "restore" && this.isContainer(idx) && gTreeData[idx].checked === 0) if (column.id == "restore" && this.isContainer(idx) && gTreeData[idx].checked === 0)
return "partial"; return "partial";
if (column.id == "title") if (column.id == "title")
@ -338,7 +340,7 @@ var treeView = {
return ""; return "";
}, },
getRowProperties: function(idx) { getRowProperties(idx) {
var winState = gTreeData[idx].parent || gTreeData[idx]; var winState = gTreeData[idx].parent || gTreeData[idx];
if (winState.ix % 2 != 0) if (winState.ix % 2 != 0)
return "alternate"; return "alternate";
@ -346,17 +348,17 @@ var treeView = {
return ""; return "";
}, },
getImageSrc: function(idx, column) { getImageSrc(idx, column) {
if (column.id == "title") if (column.id == "title")
return gTreeData[idx].src || null; return gTreeData[idx].src || null;
return null; return null;
}, },
getProgressMode : function(idx, column) { }, getProgressMode(idx, column) { },
cycleHeader: function(column) { }, cycleHeader(column) { },
cycleCell: function(idx, column) { }, cycleCell(idx, column) { },
selectionChanged: function() { }, selectionChanged() { },
performAction: function(action) { }, performAction(action) { },
performActionOnCell: function(action, index, column) { }, performActionOnCell(action, index, column) { },
getColumnProperties: function(column) { return ""; } getColumnProperties(column) { return ""; }
}; };

View File

@ -2,11 +2,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict"; /* eslint-env mozilla/frame-script */
function debug(msg) { "use strict";
Services.console.logStringMessage("SessionStoreContent: " + msg);
}
var Cu = Components.utils; var Cu = Components.utils;
var Cc = Components.classes; var Cc = Components.classes;
@ -15,6 +13,11 @@ var Cr = Components.results;
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this); Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
Cu.import("resource://gre/modules/Timer.jsm", this); Cu.import("resource://gre/modules/Timer.jsm", this);
Cu.import("resource://gre/modules/Services.jsm", this);
function debug(msg) {
Services.console.logStringMessage("SessionStoreContent: " + msg);
}
XPCOMUtils.defineLazyModuleGetter(this, "FormData", XPCOMUtils.defineLazyModuleGetter(this, "FormData",
"resource://gre/modules/FormData.jsm"); "resource://gre/modules/FormData.jsm");
@ -36,7 +39,7 @@ Cu.import("resource:///modules/sessionstore/FrameTree.jsm", this);
var gFrameTree = new FrameTree(this); var gFrameTree = new FrameTree(this);
Cu.import("resource:///modules/sessionstore/ContentRestore.jsm", this); Cu.import("resource:///modules/sessionstore/ContentRestore.jsm", this);
XPCOMUtils.defineLazyGetter(this, 'gContentRestore', XPCOMUtils.defineLazyGetter(this, "gContentRestore",
() => { return new ContentRestore(this) }); () => { return new ContentRestore(this) });
// The current epoch. // The current epoch.
@ -76,11 +79,11 @@ function createLazy(fn) {
*/ */
var EventListener = { var EventListener = {
init: function () { init() {
addEventListener("load", this, true); addEventListener("load", this, true);
}, },
handleEvent: function (event) { handleEvent(event) {
// Ignore load events from subframes. // Ignore load events from subframes.
if (event.target != content.document) { if (event.target != content.document) {
return; return;
@ -117,11 +120,11 @@ var MessageListener = {
"SessionStore:becomeActiveProcess", "SessionStore:becomeActiveProcess",
], ],
init: function () { init() {
this.MESSAGES.forEach(m => addMessageListener(m, this)); this.MESSAGES.forEach(m => addMessageListener(m, this));
}, },
receiveMessage: function ({name, data}) { receiveMessage({name, data}) {
// The docShell might be gone. Don't process messages, // The docShell might be gone. Don't process messages,
// that will just lead to errors anyway. // that will just lead to errors anyway.
if (!docShell) { if (!docShell) {
@ -230,7 +233,7 @@ var MessageListener = {
* {entries: [{url: "about:mozilla", ...}, ...], index: 1} * {entries: [{url: "about:mozilla", ...}, ...], index: 1}
*/ */
var SessionHistoryListener = { var SessionHistoryListener = {
init: function () { init() {
// The frame tree observer is needed to handle initial subframe loads. // The frame tree observer is needed to handle initial subframe loads.
// It will redundantly invalidate with the SHistoryListener in some cases // It will redundantly invalidate with the SHistoryListener in some cases
// but these invalidations are very cheap. // but these invalidations are very cheap.
@ -260,14 +263,14 @@ var SessionHistoryListener = {
addEventListener("DOMTitleChanged", this); addEventListener("DOMTitleChanged", this);
}, },
uninit: function () { uninit() {
let sessionHistory = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory; let sessionHistory = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
if (sessionHistory) { if (sessionHistory) {
sessionHistory.removeSHistoryListener(this); sessionHistory.removeSHistoryListener(this);
} }
}, },
collect: function () { collect() {
// We want to send down a historychange even for full collects in case our // 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 // 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 // enough information for a full update. collectFrom(-1) tells the collect
@ -286,7 +289,7 @@ var SessionHistoryListener = {
// and send the entire history. We always send the additional info like the current selected // 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 // 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) // if nothing else changed send an empty array and the additonal info like the selected index)
collectFrom: function (idx) { collectFrom(idx) {
if (this._fromIdx <= idx) { if (this._fromIdx <= idx) {
// If we already know that we need to update history fromn index N we can ignore any changes // 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. // tha happened with an element with index larger than N.
@ -312,44 +315,44 @@ var SessionHistoryListener = {
this.collect(); this.collect();
}, },
onFrameTreeCollected: function () { onFrameTreeCollected() {
this.collect(); this.collect();
}, },
onFrameTreeReset: function () { onFrameTreeReset() {
this.collect(); this.collect();
}, },
OnHistoryNewEntry: function (newURI, oldIndex) { OnHistoryNewEntry(newURI, oldIndex) {
this.collectFrom(oldIndex); this.collectFrom(oldIndex);
}, },
OnHistoryGoBack: function (backURI) { OnHistoryGoBack(backURI) {
this.collectFrom(kLastIndex); this.collectFrom(kLastIndex);
return true; return true;
}, },
OnHistoryGoForward: function (forwardURI) { OnHistoryGoForward(forwardURI) {
this.collectFrom(kLastIndex); this.collectFrom(kLastIndex);
return true; return true;
}, },
OnHistoryGotoIndex: function (index, gotoURI) { OnHistoryGotoIndex(index, gotoURI) {
this.collectFrom(kLastIndex); this.collectFrom(kLastIndex);
return true; return true;
}, },
OnHistoryPurge: function (numEntries) { OnHistoryPurge(numEntries) {
this.collect(); this.collect();
return true; return true;
}, },
OnHistoryReload: function (reloadURI, reloadFlags) { OnHistoryReload(reloadURI, reloadFlags) {
this.collect(); this.collect();
return true; return true;
}, },
OnHistoryReplaceEntry: function (index) { OnHistoryReplaceEntry(index) {
this.collect(); this.collect();
}, },
@ -372,12 +375,12 @@ var SessionHistoryListener = {
* {scroll: "100,100", children: [null, null, {scroll: "200,200"}]} * {scroll: "100,100", children: [null, null, {scroll: "200,200"}]}
*/ */
var ScrollPositionListener = { var ScrollPositionListener = {
init: function () { init() {
addEventListener("scroll", this); addEventListener("scroll", this);
gFrameTree.addObserver(this); gFrameTree.addObserver(this);
}, },
handleEvent: function (event) { handleEvent(event) {
let frame = event.target.defaultView; let frame = event.target.defaultView;
// Don't collect scroll data for frames created at or after the load event // Don't collect scroll data for frames created at or after the load event
@ -387,15 +390,15 @@ var ScrollPositionListener = {
} }
}, },
onFrameTreeCollected: function () { onFrameTreeCollected() {
MessageQueue.push("scroll", () => this.collect()); MessageQueue.push("scroll", () => this.collect());
}, },
onFrameTreeReset: function () { onFrameTreeReset() {
MessageQueue.push("scroll", () => null); MessageQueue.push("scroll", () => null);
}, },
collect: function () { collect() {
return gFrameTree.map(ScrollPosition.collect); return gFrameTree.map(ScrollPosition.collect);
} }
}; };
@ -418,13 +421,13 @@ var ScrollPositionListener = {
* } * }
*/ */
var FormDataListener = { var FormDataListener = {
init: function () { init() {
addEventListener("input", this, true); addEventListener("input", this, true);
addEventListener("change", this, true); addEventListener("change", this, true);
gFrameTree.addObserver(this); gFrameTree.addObserver(this);
}, },
handleEvent: function (event) { handleEvent(event) {
let frame = event.target.ownerGlobal; let frame = event.target.ownerGlobal;
// Don't collect form data for frames created at or after the load event // Don't collect form data for frames created at or after the load event
@ -434,11 +437,11 @@ var FormDataListener = {
} }
}, },
onFrameTreeReset: function () { onFrameTreeReset() {
MessageQueue.push("formdata", () => null); MessageQueue.push("formdata", () => null);
}, },
collect: function () { collect() {
return gFrameTree.map(FormData.collect); return gFrameTree.map(FormData.collect);
} }
}; };
@ -455,18 +458,18 @@ var FormDataListener = {
* {pageStyle: "Dusk", children: [null, {pageStyle: "Mozilla"}]} * {pageStyle: "Dusk", children: [null, {pageStyle: "Mozilla"}]}
*/ */
var PageStyleListener = { var PageStyleListener = {
init: function () { init() {
Services.obs.addObserver(this, "author-style-disabled-changed", false); Services.obs.addObserver(this, "author-style-disabled-changed", false);
Services.obs.addObserver(this, "style-sheet-applicable-state-changed", false); Services.obs.addObserver(this, "style-sheet-applicable-state-changed", false);
gFrameTree.addObserver(this); gFrameTree.addObserver(this);
}, },
uninit: function () { uninit() {
Services.obs.removeObserver(this, "author-style-disabled-changed"); Services.obs.removeObserver(this, "author-style-disabled-changed");
Services.obs.removeObserver(this, "style-sheet-applicable-state-changed"); Services.obs.removeObserver(this, "style-sheet-applicable-state-changed");
}, },
observe: function (subject, topic) { observe(subject, topic) {
let frame = subject.defaultView; let frame = subject.defaultView;
if (frame && gFrameTree.contains(frame)) { if (frame && gFrameTree.contains(frame)) {
@ -474,15 +477,15 @@ var PageStyleListener = {
} }
}, },
collect: function () { collect() {
return PageStyle.collect(docShell, gFrameTree); return PageStyle.collect(docShell, gFrameTree);
}, },
onFrameTreeCollected: function () { onFrameTreeCollected() {
MessageQueue.push("pageStyle", () => this.collect()); MessageQueue.push("pageStyle", () => this.collect());
}, },
onFrameTreeReset: function () { onFrameTreeReset() {
MessageQueue.push("pageStyle", () => null); MessageQueue.push("pageStyle", () => null);
} }
}; };
@ -503,14 +506,14 @@ var DocShellCapabilitiesListener = {
*/ */
_latestCapabilities: "", _latestCapabilities: "",
init: function () { init() {
gFrameTree.addObserver(this); gFrameTree.addObserver(this);
}, },
/** /**
* onFrameTreeReset() is called as soon as we start loading a page. * onFrameTreeReset() is called as soon as we start loading a page.
*/ */
onFrameTreeReset: function() { onFrameTreeReset() {
// The order of docShell capabilities cannot change while we're running // The order of docShell capabilities cannot change while we're running
// so calling join() without sorting before is totally sufficient. // so calling join() without sorting before is totally sufficient.
let caps = DocShellCapabilities.collect(docShell).join(","); let caps = DocShellCapabilities.collect(docShell).join(",");
@ -533,23 +536,23 @@ var DocShellCapabilitiesListener = {
* as keys and per-host DOMSessionStorage data as values. * as keys and per-host DOMSessionStorage data as values.
*/ */
var SessionStorageListener = { var SessionStorageListener = {
init: function () { init() {
addEventListener("MozSessionStorageChanged", this, true); addEventListener("MozSessionStorageChanged", this, true);
Services.obs.addObserver(this, "browser:purge-domain-data", false); Services.obs.addObserver(this, "browser:purge-domain-data", false);
gFrameTree.addObserver(this); gFrameTree.addObserver(this);
}, },
uninit: function () { uninit() {
Services.obs.removeObserver(this, "browser:purge-domain-data"); Services.obs.removeObserver(this, "browser:purge-domain-data");
}, },
handleEvent: function (event) { handleEvent(event) {
if (gFrameTree.contains(event.target)) { if (gFrameTree.contains(event.target)) {
this.collectFromEvent(event); this.collectFromEvent(event);
} }
}, },
observe: function () { observe() {
// Collect data on the next tick so that any other observer // Collect data on the next tick so that any other observer
// that needs to purge data can do its work first. // that needs to purge data can do its work first.
setTimeout(() => this.collect(), 0); setTimeout(() => this.collect(), 0);
@ -567,7 +570,7 @@ var SessionStorageListener = {
// we also don't want to cause an OOM here, we use a quick and memory- // we also don't want to cause an OOM here, we use a quick and memory-
// efficient approximation: we compute the total sum of string lengths // efficient approximation: we compute the total sum of string lengths
// involved in this object. // involved in this object.
estimateStorageSize: function(collected) { estimateStorageSize(collected) {
if (!collected) { if (!collected) {
return 0; return 0;
} }
@ -593,11 +596,11 @@ var SessionStorageListener = {
// reset these changes. // reset these changes.
_changes: undefined, _changes: undefined,
resetChanges: function () { resetChanges() {
this._changes = undefined; this._changes = undefined;
}, },
collectFromEvent: function (event) { collectFromEvent(event) {
// TODO: we should take browser.sessionstore.dom_storage_limit into an account here. // TODO: we should take browser.sessionstore.dom_storage_limit into an account here.
if (docShell) { if (docShell) {
let {url, key, newValue} = event; let {url, key, newValue} = event;
@ -622,7 +625,7 @@ var SessionStorageListener = {
} }
}, },
collect: function () { collect() {
if (docShell) { if (docShell) {
// We need the entire session storage, let's reset the pending individual change // We need the entire session storage, let's reset the pending individual change
// messages. // messages.
@ -649,11 +652,11 @@ var SessionStorageListener = {
} }
}, },
onFrameTreeCollected: function () { onFrameTreeCollected() {
this.collect(); this.collect();
}, },
onFrameTreeReset: function () { onFrameTreeReset() {
this.collect(); this.collect();
} }
}; };
@ -669,7 +672,7 @@ var SessionStorageListener = {
* not saved. * not saved.
*/ */
var PrivacyListener = { var PrivacyListener = {
init: function() { init() {
docShell.addWeakPrivacyTransitionObserver(this); docShell.addWeakPrivacyTransitionObserver(this);
// Check that value at startup as it might have // Check that value at startup as it might have
@ -680,7 +683,7 @@ var PrivacyListener = {
}, },
// Ci.nsIPrivacyTransitionObserver // Ci.nsIPrivacyTransitionObserver
privateModeChanged: function(enabled) { privateModeChanged(enabled) {
MessageQueue.push("isPrivate", () => enabled || null); MessageQueue.push("isPrivate", () => enabled || null);
}, },
@ -774,7 +777,7 @@ var MessageQueue = {
* A function that returns the value that will be sent to the parent * A function that returns the value that will be sent to the parent
* process. * process.
*/ */
push: function (key, fn) { push(key, fn) {
this._data.set(key, createLazy(fn)); this._data.set(key, createLazy(fn));
if (!this._timeout && !this._timeoutDisabled) { if (!this._timeout && !this._timeoutDisabled) {
@ -790,7 +793,7 @@ var MessageQueue = {
* {flushID: 123} to specify that this is a flush * {flushID: 123} to specify that this is a flush
* {isFinal: true} to signal this is the final message sent on unload * {isFinal: true} to signal this is the final message sent on unload
*/ */
send: function (options = {}) { send(options = {}) {
// Looks like we have been called off a timeout after the tab has been // 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 // closed. The docShell is gone now and we can just return here as there
// is nothing to do. // is nothing to do.
@ -832,13 +835,14 @@ var MessageQueue = {
isFinal: options.isFinal || false, isFinal: options.isFinal || false,
epoch: gCurrentEpoch epoch: gCurrentEpoch
}); });
} catch (ex if ex && ex.result == Cr.NS_ERROR_OUT_OF_MEMORY) { } catch (ex) {
let telemetry = { if (ex && ex.result == Cr.NS_ERROR_OUT_OF_MEMORY) {
FX_SESSION_RESTORE_SEND_UPDATE_CAUSED_OOM: 1 sendAsyncMessage("SessionStore:error", {
}; telemetry: {
sendAsyncMessage("SessionStore:error", { FX_SESSION_RESTORE_SEND_UPDATE_CAUSED_OOM: 1
telemetry }
}); });
}
} }
}, },
}; };

View File

@ -65,7 +65,7 @@ consoleMsg.init(aMsg, aException.fileName, null, aException.lineNumber, 0, Ci.ns
Services.console.logMessage(consoleMsg); Services.console.logMessage(consoleMsg);
} }
var gOnceInitializedDeferred = (function () { var gOnceInitializedDeferred = (function() {
let deferred = {}; let deferred = {};
deferred.promise = new Promise((resolve, reject) => { deferred.promise = new Promise((resolve, reject) => {
@ -127,7 +127,7 @@ SessionStartup.prototype = {
* @param source The Session State string read from disk. * @param source The Session State string read from disk.
* @param parsed The object obtained by parsing |source| as JSON. * @param parsed The object obtained by parsing |source| as JSON.
*/ */
_onSessionFileRead: function ({source, parsed, noFilesFound}) { _onSessionFileRead({source, parsed, noFilesFound}) {
this._initialized = true; this._initialized = true;
// Let observers modify the state before it is used // Let observers modify the state before it is used
@ -173,35 +173,30 @@ SessionStartup.prototype = {
// If the previous session finished writing the final state, we'll // If the previous session finished writing the final state, we'll
// assume there was no crash. // assume there was no crash.
this._previousSessionCrashed = !checkpoints["sessionstore-final-state-write-complete"]; this._previousSessionCrashed = !checkpoints["sessionstore-final-state-write-complete"];
} else if (noFilesFound) {
} else {
// If the Crash Monitor could not load a checkpoints file it will // If the Crash Monitor could not load a checkpoints file it will
// provide null. This could occur on the first run after updating to // provide null. This could occur on the first run after updating to
// a version including the Crash Monitor, or if the checkpoints file // a version including the Crash Monitor, or if the checkpoints file
// was removed, or on first startup with this profile, or after Firefox Reset. // was removed, or on first startup with this profile, or after Firefox Reset.
if (noFilesFound) { // There was no checkpoints file and no sessionstore.js or its backups
// There was no checkpoints file and no sessionstore.js or its backups // so we will assume that this was a fresh profile.
// so we will assume that this was a fresh profile. this._previousSessionCrashed = false;
this._previousSessionCrashed = false; } else {
// If this is the first run after an update, sessionstore.js should
// still contain the session.state flag to indicate if the session
// crashed. If it is not present, we will assume this was not the first
// run after update and the checkpoints file was somehow corrupted or
// removed by a crash.
//
// If the session.state flag is present, we will fallback to using it
// for crash detection - If the last write of sessionstore.js had it
// set to "running", we crashed.
let stateFlagPresent = (this._initialState.session &&
this._initialState.session.state);
} else { this._previousSessionCrashed = !stateFlagPresent ||
// If this is the first run after an update, sessionstore.js should (this._initialState.session.state == STATE_RUNNING_STR);
// still contain the session.state flag to indicate if the session
// crashed. If it is not present, we will assume this was not the first
// run after update and the checkpoints file was somehow corrupted or
// removed by a crash.
//
// If the session.state flag is present, we will fallback to using it
// for crash detection - If the last write of sessionstore.js had it
// set to "running", we crashed.
let stateFlagPresent = (this._initialState.session &&
this._initialState.session.state);
this._previousSessionCrashed = !stateFlagPresent ||
(this._initialState.session.state == STATE_RUNNING_STR);
}
} }
// Report shutdown success via telemetry. Shortcoming here are // Report shutdown success via telemetry. Shortcoming here are
@ -293,7 +288,7 @@ SessionStartup.prototype = {
* crash, this method returns false. * crash, this method returns false.
* @returns bool * @returns bool
*/ */
isAutomaticRestoreEnabled: function () { isAutomaticRestoreEnabled() {
return Services.prefs.getBoolPref("browser.sessionstore.resume_session_once") || return Services.prefs.getBoolPref("browser.sessionstore.resume_session_once") ||
Services.prefs.getIntPref("browser.startup.page") == BROWSER_STARTUP_RESUME_SESSION; Services.prefs.getIntPref("browser.startup.page") == BROWSER_STARTUP_RESUME_SESSION;
}, },
@ -302,7 +297,7 @@ SessionStartup.prototype = {
* Determines whether there is a pending session restore. * Determines whether there is a pending session restore.
* @returns bool * @returns bool
*/ */
_willRestore: function () { _willRestore() {
return this._sessionType == Ci.nsISessionStartup.RECOVER_SESSION || return this._sessionType == Ci.nsISessionStartup.RECOVER_SESSION ||
this._sessionType == Ci.nsISessionStartup.RESUME_SESSION; this._sessionType == Ci.nsISessionStartup.RESUME_SESSION;
}, },

View File

@ -26,7 +26,7 @@ function SessionStoreService() {}
// The SessionStore module's object is frozen. We need to modify our prototype // The SessionStore module's object is frozen. We need to modify our prototype
// and add some properties so let's just copy the SessionStore object. // and add some properties so let's just copy the SessionStore object.
Object.keys(SessionStore).forEach(function (aName) { Object.keys(SessionStore).forEach(function(aName) {
let desc = Object.getOwnPropertyDescriptor(SessionStore, aName); let desc = Object.getOwnPropertyDescriptor(SessionStore, aName);
Object.defineProperty(SessionStoreService.prototype, aName, desc); Object.defineProperty(SessionStoreService.prototype, aName, desc);
}); });

View File

@ -1,15 +1,15 @@
"use strict"; "use strict";
const PREF = 'network.cookie.cookieBehavior'; const PREF = "network.cookie.cookieBehavior";
const PAGE_URL = 'http://mochi.test:8888/browser/' + const PAGE_URL = "http://mochi.test:8888/browser/" +
'browser/components/sessionstore/test/browser_1234021_page.html'; "browser/components/sessionstore/test/browser_1234021_page.html";
const BEHAVIOR_REJECT = 2; const BEHAVIOR_REJECT = 2;
add_task(function* test() { add_task(function* test() {
yield pushPrefs([PREF, BEHAVIOR_REJECT]); yield pushPrefs([PREF, BEHAVIOR_REJECT]);
yield BrowserTestUtils.withNewTab({ yield BrowserTestUtils.withNewTab({
gBrowser: gBrowser, gBrowser,
url: PAGE_URL url: PAGE_URL
}, function* handler(aBrowser) { }, function* handler(aBrowser) {
yield TabStateFlusher.flush(aBrowser); yield TabStateFlusher.flush(aBrowser);

View File

@ -32,10 +32,10 @@ function test() {
} }
}); });
function test(aLambda) { function checkNoThrow(aLambda) {
try { try {
return aLambda() || true; return aLambda() || true;
} catch(ex) { } } catch (ex) { }
return false; return false;
} }
@ -73,9 +73,9 @@ function test() {
(aValue.indexOf(aIx) > -1) == aOpt.selected); (aValue.indexOf(aIx) > -1) == aOpt.selected);
} }
////////////////////////////////////////////////////////////////// /**
// Test (B) : Session data restoration between windows // * Test (B) : Session data restoration between windows
////////////////////////////////////////////////////////////////// */
let rootDir = getRootDirectory(gTestPath); let rootDir = getRootDirectory(gTestPath);
const testURL = rootDir + "browser_248970_b_sample.html"; const testURL = rootDir + "browser_248970_b_sample.html";
@ -93,7 +93,6 @@ function test() {
"getClosedTabCount should return zero or at most max_tabs_undo"); "getClosedTabCount should return zero or at most max_tabs_undo");
// setup a state for tab (A) so we can check later that is restored // setup a state for tab (A) so we can check later that is restored
let key = "key";
let value = "Value " + Math.random(); let value = "Value " + Math.random();
let state = { entries: [{ url: testURL }], extData: { key: value } }; let state = { entries: [{ url: testURL }], extData: { key: value } };
@ -117,15 +116,15 @@ function test() {
"getClosedTabCount has increased after closing a tab"); "getClosedTabCount has increased after closing a tab");
// verify tab: (A), in undo list // verify tab: (A), in undo list
let tab_A_restored = test(() => ss.undoCloseTab(aWin, 0)); let tab_A_restored = checkNoThrow(() => ss.undoCloseTab(aWin, 0));
ok(tab_A_restored, "a tab is in undo list"); ok(tab_A_restored, "a tab is in undo list");
promiseTabRestored(tab_A_restored).then(() => { promiseTabRestored(tab_A_restored).then(() => {
is(testURL, tab_A_restored.linkedBrowser.currentURI.spec, is(testURL, tab_A_restored.linkedBrowser.currentURI.spec,
"it's the same tab that we expect"); "it's the same tab that we expect");
aWin.gBrowser.removeTab(tab_A_restored); aWin.gBrowser.removeTab(tab_A_restored);
whenNewWindowLoaded({ private: true }, function(aWin) { whenNewWindowLoaded({ private: true }, function(win) {
windowsToClose.push(aWin); windowsToClose.push(win);
// setup a state for tab (B) so we can check that its duplicated // setup a state for tab (B) so we can check that its duplicated
// properly // properly
@ -135,14 +134,14 @@ function test() {
entries: [{ url: testURL2 }], extData: { key1: value1 } entries: [{ url: testURL2 }], extData: { key1: value1 }
}; };
let tab_B = aWin.gBrowser.addTab(testURL2); let tab_B = win.gBrowser.addTab(testURL2);
promiseTabState(tab_B, state1).then(() => { promiseTabState(tab_B, state1).then(() => {
// populate tab: (B) with different form data // populate tab: (B) with different form data
for (let item in fieldList) for (let item in fieldList)
setFormValue(tab_B, item, fieldList[item]); setFormValue(tab_B, item, fieldList[item]);
// duplicate tab: (B) // duplicate tab: (B)
let tab_C = aWin.gBrowser.duplicateTab(tab_B); let tab_C = win.gBrowser.duplicateTab(tab_B);
promiseTabRestored(tab_C).then(() => { promiseTabRestored(tab_C).then(() => {
// verify the correctness of the duplicated tab // verify the correctness of the duplicated tab
is(ss.getTabValue(tab_C, key1), value1, is(ss.getTabValue(tab_C, key1), value1,
@ -153,8 +152,8 @@ function test() {
"The value for \"" + item + "\" was correctly duplicated"); "The value for \"" + item + "\" was correctly duplicated");
// private browsing session, close tab: (C) and (B) // private browsing session, close tab: (C) and (B)
aWin.gBrowser.removeTab(tab_C); win.gBrowser.removeTab(tab_C);
aWin.gBrowser.removeTab(tab_B); win.gBrowser.removeTab(tab_B);
finish(); finish();
}); });

View File

@ -5,40 +5,41 @@
function test() { function test() {
/** Test for Bug 345898 **/ /** Test for Bug 345898 **/
function test(aLambda) {
try {
aLambda();
return false;
}
catch (ex) {
return ex.name == "NS_ERROR_ILLEGAL_VALUE" ||
ex.name == "NS_ERROR_FAILURE";
}
}
// all of the following calls with illegal arguments should throw NS_ERROR_ILLEGAL_VALUE // all of the following calls with illegal arguments should throw NS_ERROR_ILLEGAL_VALUE
ok(test(() => ss.getWindowState({})), Assert.throws(() => ss.getWindowState({}),
"Invalid window for getWindowState throws"); /NS_ERROR_ILLEGAL_VALUE/,
ok(test(() => ss.setWindowState({}, "", false)), "Invalid window for getWindowState throws");
"Invalid window for setWindowState throws"); Assert.throws(() => ss.setWindowState({}, "", false),
ok(test(() => ss.getTabState({})), /NS_ERROR_ILLEGAL_VALUE/,
"Invalid tab for getTabState throws"); "Invalid window for setWindowState throws");
ok(test(() => ss.setTabState({}, "{}")), Assert.throws(() => ss.getTabState({}),
"Invalid tab state for setTabState throws"); /NS_ERROR_FAILURE/,
ok(test(() => ss.setTabState({}, JSON.stringify({ entries: [] }))), "Invalid tab for getTabState throws");
"Invalid tab for setTabState throws"); Assert.throws(() => ss.setTabState({}, "{}"),
ok(test(() => ss.duplicateTab({}, {})), /NS_ERROR_FAILURE/,
"Invalid tab for duplicateTab throws"); "Invalid tab state for setTabState throws");
ok(test(() => ss.duplicateTab({}, gBrowser.selectedTab)), Assert.throws(() => ss.setTabState({}, JSON.stringify({ entries: [] })),
"Invalid window for duplicateTab throws"); /NS_ERROR_FAILURE/,
ok(test(() => ss.getClosedTabData({})), "Invalid tab for setTabState throws");
"Invalid window for getClosedTabData throws"); Assert.throws(() => ss.duplicateTab({}, {}),
ok(test(() => ss.undoCloseTab({}, 0)), /NS_ERROR_FAILURE/,
"Invalid window for undoCloseTab throws"); "Invalid tab for duplicateTab throws");
ok(test(() => ss.undoCloseTab(window, -1)), Assert.throws(() => ss.duplicateTab({}, gBrowser.selectedTab),
"Invalid index for undoCloseTab throws"); /NS_ERROR_ILLEGAL_VALUE/,
ok(test(() => ss.getWindowValue({}, "")), "Invalid window for duplicateTab throws");
"Invalid window for getWindowValue throws"); Assert.throws(() => ss.getClosedTabData({}),
ok(test(() => ss.setWindowValue({}, "", "")), /NS_ERROR_ILLEGAL_VALUE/,
"Invalid window for setWindowValue throws"); "Invalid window for getClosedTabData throws");
Assert.throws(() => ss.undoCloseTab({}, 0),
/NS_ERROR_ILLEGAL_VALUE/,
"Invalid window for undoCloseTab throws");
Assert.throws(() => ss.undoCloseTab(window, -1),
/NS_ERROR_ILLEGAL_VALUE/,
"Invalid index for undoCloseTab throws");
Assert.throws(() => ss.getWindowValue({}, ""),
/NS_ERROR_ILLEGAL_VALUE/,
"Invalid window for getWindowValue throws");
Assert.throws(() => ss.setWindowValue({}, "", ""),
/NS_ERROR_ILLEGAL_VALUE/,
"Invalid window for setWindowValue throws");
} }

View File

@ -12,14 +12,13 @@ add_task(function* () {
function test(aLambda) { function test(aLambda) {
try { try {
return aLambda() || true; return aLambda() || true;
} } catch (ex) { }
catch (ex) { }
return false; return false;
} }
//////////////////////////// /**
// setWindowValue, et al. // * setWindowValue, et al.
//////////////////////////// */
let key = "Unique name: " + Date.now(); let key = "Unique name: " + Date.now();
let value = "Unique value: " + Math.random(); let value = "Unique value: " + Math.random();
@ -38,9 +37,9 @@ add_task(function* () {
// test deleting a non-existent value // test deleting a non-existent value
ok(test(() => ss.deleteWindowValue(window, key)), "delete non-existent window value"); ok(test(() => ss.deleteWindowValue(window, key)), "delete non-existent window value");
///////////////////////// /**
// setTabValue, et al. // * setTabValue, et al.
///////////////////////// */
key = "Unique name: " + Math.random(); key = "Unique name: " + Math.random();
value = "Unique value: " + Date.now(); value = "Unique value: " + Date.now();
let tab = gBrowser.addTab(); let tab = gBrowser.addTab();
@ -64,9 +63,9 @@ add_task(function* () {
// clean up // clean up
yield promiseRemoveTab(tab); yield promiseRemoveTab(tab);
///////////////////////////////////// /**
// getClosedTabCount, undoCloseTab // * getClosedTabCount, undoCloseTab
///////////////////////////////////// */
// get closed tab count // get closed tab count
let count = ss.getClosedTabCount(window); let count = ss.getClosedTabCount(window);

View File

@ -76,7 +76,7 @@ add_task(function* setup() {
document.documentElement.setAttribute("windowtype", "navigator:testrunner"); document.documentElement.setAttribute("windowtype", "navigator:testrunner");
registerCleanupFunction(() => { registerCleanupFunction(() => {
document.documentElement.setAttribute("windowtype", "navigator:browser"); document.documentElement.setAttribute("windowtype", oldWinType);
}); });
}); });
@ -154,7 +154,7 @@ let setupTest = Task.async(function*(options, testFunction) {
* The browser window to load the tabs in * The browser window to load the tabs in
*/ */
function injectTestTabs(win) { function injectTestTabs(win) {
TEST_URLS.forEach(function (url) { TEST_URLS.forEach(function(url) {
win.gBrowser.addTab(url); win.gBrowser.addTab(url);
}); });
} }
@ -471,4 +471,3 @@ add_task(function* test_mac_notifications() {
"Got expected browser-lastwindow-close-granted notifications"); "Got expected browser-lastwindow-close-granted notifications");
}); });
}); });

View File

@ -35,6 +35,7 @@ add_task(function* () {
}); });
function promiseSHistoryCount(browser) { function promiseSHistoryCount(browser) {
/* eslint-env mozilla/frame-script */
return ContentTask.spawn(browser, null, function* () { return ContentTask.spawn(browser, null, function* () {
return docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory.count; return docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory.count;
}); });

View File

@ -29,7 +29,7 @@ function test() {
// Mark the window with some unique data to be restored later on. // Mark the window with some unique data to be restored later on.
ss.setWindowValue(newWin, uniqueKey, uniqueValue); ss.setWindowValue(newWin, uniqueKey, uniqueValue);
let [txt, chk] = newWin.content.document.querySelectorAll("#txt, #chk"); let [txt] = newWin.content.document.querySelectorAll("#txt");
txt.value = uniqueText; txt.value = uniqueText;
let browser = newWin.gBrowser.selectedBrowser; let browser = newWin.gBrowser.selectedBrowser;
@ -73,7 +73,8 @@ function test() {
is(newWin2.gBrowser.currentURI.spec, TEST_URL, is(newWin2.gBrowser.currentURI.spec, TEST_URL,
"The window correctly restored the URL"); "The window correctly restored the URL");
let [txt, chk] = newWin2.content.document.querySelectorAll("#txt, #chk"); let chk;
[txt, chk] = newWin2.content.document.querySelectorAll("#txt, #chk");
ok(txt.value == uniqueText && chk.checked, ok(txt.value == uniqueText && chk.checked,
"The window correctly restored the form"); "The window correctly restored the form");
is(ss.getWindowValue(newWin2, uniqueKey), uniqueValue, is(ss.getWindowValue(newWin2, uniqueKey), uniqueValue,

View File

@ -73,4 +73,4 @@ add_task(function* test_closed_window_states() {
other: {popup: 0, normal: 3}}; other: {popup: 0, normal: 3}};
yield testWindows(windowsToOpen2, expectedResults2); yield testWindows(windowsToOpen2, expectedResults2);
}); });

View File

@ -6,7 +6,7 @@ Components.utils.import("resource://gre/modules/ForgetAboutSite.jsm");
function waitForClearHistory(aCallback) { function waitForClearHistory(aCallback) {
let observer = { let observer = {
observe: function(aSubject, aTopic, aData) { observe(aSubject, aTopic, aData) {
Services.obs.removeObserver(this, "browser:purge-domain-data"); Services.obs.removeObserver(this, "browser:purge-domain-data");
setTimeout(aCallback, 0); setTimeout(aCallback, 0);
} }

View File

@ -12,7 +12,7 @@ function test() {
// Make sure the functionality added in bug 943339 doesn't affect the results // Make sure the functionality added in bug 943339 doesn't affect the results
gPrefService.setIntPref("browser.sessionstore.max_serialize_back", -1); gPrefService.setIntPref("browser.sessionstore.max_serialize_back", -1);
gPrefService.setIntPref("browser.sessionstore.max_serialize_forward", -1); gPrefService.setIntPref("browser.sessionstore.max_serialize_forward", -1);
registerCleanupFunction(function () { registerCleanupFunction(function() {
gPrefService.clearUserPref("browser.sessionstore.max_serialize_back"); gPrefService.clearUserPref("browser.sessionstore.max_serialize_back");
gPrefService.clearUserPref("browser.sessionstore.max_serialize_forward"); gPrefService.clearUserPref("browser.sessionstore.max_serialize_forward");
}); });

View File

@ -41,7 +41,7 @@ add_task(function* test_restore_nonstandard_input_values() {
} }
is(countGood, 4, "Saved text for non-standard input fields"); is(countGood, 4, "Saved text for non-standard input fields");
is(countBad, 0, "Didn't save text for ignored field types"); is(countBad, 0, "Didn't save text for ignored field types");
}); });
function setFormElementValues(browser, data) { function setFormElementValues(browser, data) {

View File

@ -24,15 +24,15 @@ function test() {
frameCount = 0; frameCount = 0;
let tab2 = gBrowser.duplicateTab(tab); let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("load", function(aEvent) { tab2.linkedBrowser.addEventListener("load", function(eventTab2) {
// wait for all frames to load (and reload!) completely // wait for all frames to load (and reload!) completely
if (frameCount++ < 2) if (frameCount++ < 2)
return; return;
tab2.linkedBrowser.removeEventListener("load", arguments.callee, true); tab2.linkedBrowser.removeEventListener("load", arguments.callee, true);
executeSoon(function() { executeSoon(function() {
let iframes = tab2.linkedBrowser.contentWindow.frames; let iframesTab2 = tab2.linkedBrowser.contentWindow.frames;
if (iframes[1].document.body.innerHTML !== uniqueValue) { if (iframesTab2[1].document.body.innerHTML !== uniqueValue) {
// Poll again the value, since we can't ensure to run // Poll again the value, since we can't ensure to run
// after SessionStore has injected innerHTML value. // after SessionStore has injected innerHTML value.
// See bug 521802. // See bug 521802.
@ -41,14 +41,13 @@ function test() {
return; return;
} }
is(iframes[1].document.body.innerHTML, uniqueValue, is(iframesTab2[1].document.body.innerHTML, uniqueValue,
"rich textarea's content correctly duplicated"); "rich textarea's content correctly duplicated");
let innerDomain = null; let innerDomain = null;
try { try {
innerDomain = iframes[0].document.domain; innerDomain = iframesTab2[0].document.domain;
} } catch (ex) { /* throws for chrome: documents */ }
catch (ex) { /* throws for chrome: documents */ }
is(innerDomain, "mochi.test", "XSS exploit prevented!"); is(innerDomain, "mochi.test", "XSS exploit prevented!");
// clean up // clean up

View File

@ -36,6 +36,6 @@
}); });
frames[1].document.designMode = "on"; frames[1].document.designMode = "on";
}; }
</script> </script>
</body> </body>

View File

@ -26,8 +26,7 @@ function test() {
try { try {
aFunction(); aFunction();
return false; return false;
} } catch (ex) {
catch (ex) {
return ex.name == "NS_ERROR_ILLEGAL_VALUE"; return ex.name == "NS_ERROR_ILLEGAL_VALUE";
} }
} }

View File

@ -18,7 +18,7 @@ function test() {
return; return;
tab.linkedBrowser.removeEventListener("load", arguments.callee, true); tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
let tab2 = gBrowser.duplicateTab(tab); let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("461743", function(aEvent) { tab2.linkedBrowser.addEventListener("461743", function(eventTab2) {
tab2.linkedBrowser.removeEventListener("461743", arguments.callee, true); tab2.linkedBrowser.removeEventListener("461743", arguments.callee, true);
is(aEvent.data, "done", "XSS injection was attempted"); is(aEvent.data, "done", "XSS injection was attempted");

View File

@ -35,7 +35,7 @@
xhr.send(null); xhr.send(null);
} }
function done() { function done() {
var event = new MessageEvent('461743', { bubbles: true, cancelable: false, var event = new MessageEvent("461743", { bubbles: true, cancelable: false,
data: "done", origin: location.href, data: "done", origin: location.href,
source: window }); source: window });
document.dispatchEvent(event); document.dispatchEvent(event);
@ -51,6 +51,6 @@
frames[0].document.addEventListener("DOMNodeInserted", done, true); frames[0].document.addEventListener("DOMNodeInserted", done, true);
frames[0].document.designMode = "on"; frames[0].document.designMode = "on";
}; }
</script> </script>
</body> </body>

View File

@ -35,6 +35,6 @@ add_task(function* test_check_urls_before_restoring() {
function getState(url) { function getState(url) {
return JSON.stringify({ return JSON.stringify({
entries: [{url: URL, triggeringPrincipal_base64}], entries: [{url: URL, triggeringPrincipal_base64}],
formdata: {url: url, id: {text: "foobar"}} formdata: {url, id: {text: "foobar"}}
}); });
} }

View File

@ -41,7 +41,7 @@ add_task(function* () {
Assert.equal(content.frames[1].document.getElementById("out2").value, Assert.equal(content.frames[1].document.getElementById("out2").value,
"", "id prefixes can't be faked"); "", "id prefixes can't be faked");
// Disabled for now, Bug 588077 // Disabled for now, Bug 588077
//Assert.equal(content.frames[0].frames[1].document.getElementById("in1").value, // Assert.equal(content.frames[0].frames[1].document.getElementById("in1").value,
// "", "id prefixes aren't mixed up"); // "", "id prefixes aren't mixed up");
Assert.equal(content.frames[1].frames[0].document.getElementById("in1").value, Assert.equal(content.frames[1].frames[0].document.getElementById("in1").value,
"", "id prefixes aren't mixed up"); "", "id prefixes aren't mixed up");

View File

@ -6,7 +6,7 @@ Components.utils.import("resource://gre/modules/ForgetAboutSite.jsm");
function waitForClearHistory(aCallback) { function waitForClearHistory(aCallback) {
let observer = { let observer = {
observe: function(aSubject, aTopic, aData) { observe(aSubject, aTopic, aData) {
Services.obs.removeObserver(this, "browser:purge-domain-data"); Services.obs.removeObserver(this, "browser:purge-domain-data");
setTimeout(aCallback, 0); setTimeout(aCallback, 0);
} }

View File

@ -44,7 +44,7 @@
} }
document.getElementById("state").textContent = "done"; document.getElementById("state").textContent = "done";
var event = new MessageEvent('464620_a', { bubbles: true, cancelable: false, var event = new MessageEvent("464620_a", { bubbles: true, cancelable: false,
data: "done", origin: location.href, data: "done", origin: location.href,
source: window }); source: window });
document.dispatchEvent(event); document.dispatchEvent(event);

View File

@ -21,7 +21,7 @@ function test() {
executeSoon(function() { executeSoon(function() {
frameCount = 0; frameCount = 0;
let tab2 = gBrowser.duplicateTab(tab); let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("464620_a", function(aEvent) { tab2.linkedBrowser.addEventListener("464620_a", function(eventTab2) {
tab2.linkedBrowser.removeEventListener("464620_a", arguments.callee, true); tab2.linkedBrowser.removeEventListener("464620_a", arguments.callee, true);
is(aEvent.data, "done", "XSS injection was attempted"); is(aEvent.data, "done", "XSS injection was attempted");

View File

@ -47,7 +47,7 @@
} }
document.getElementById("state").textContent = "done"; document.getElementById("state").textContent = "done";
var event = new MessageEvent('464620_b', { bubbles: true, cancelable: false, var event = new MessageEvent("464620_b", { bubbles: true, cancelable: false,
data: "done", origin: location.href, data: "done", origin: location.href,
source: window }); source: window });
document.dispatchEvent(event); document.dispatchEvent(event);

View File

@ -21,7 +21,7 @@ function test() {
executeSoon(function() { executeSoon(function() {
frameCount = 0; frameCount = 0;
let tab2 = gBrowser.duplicateTab(tab); let tab2 = gBrowser.duplicateTab(tab);
tab2.linkedBrowser.addEventListener("464620_b", function(aEvent) { tab2.linkedBrowser.addEventListener("464620_b", function(eventTab2) {
tab2.linkedBrowser.removeEventListener("464620_b", arguments.callee, true); tab2.linkedBrowser.removeEventListener("464620_b", arguments.callee, true);
is(aEvent.data, "done", "XSS injection was attempted"); is(aEvent.data, "done", "XSS injection was attempted");

View File

@ -12,8 +12,7 @@
window.addEventListener("DOMContentLoaded", function() { window.addEventListener("DOMContentLoaded", function() {
if (!document.location.hash) { if (!document.location.hash) {
document.location.hash = "#ready"; document.location.hash = "#ready";
} } else {
else {
document.getElementById("thief").type = "file"; document.getElementById("thief").type = "file";
document.getElementById("reverse_thief").type = "text"; document.getElementById("reverse_thief").type = "text";
} }

View File

@ -26,7 +26,7 @@ const STATE3 = createEntries(JSON.stringify(CRASH_STATE));
function createEntries(sessionData) { function createEntries(sessionData) {
return { return {
entries: [{url: "about:sessionrestore", triggeringPrincipal_base64}], entries: [{url: "about:sessionrestore", triggeringPrincipal_base64}],
formdata: {id: {sessionData: sessionData}, url: "about:sessionrestore"} formdata: {id: {sessionData}, url: "about:sessionrestore"}
}; };
} }

View File

@ -22,7 +22,7 @@ add_task(function* () {
yield TabStateFlusher.flush(browser); yield TabStateFlusher.flush(browser);
let tabState = JSON.parse(ss.getTabState(tab)); let tabState = JSON.parse(ss.getTabState(tab));
is(tabState.entries[0].referrer, REFERRER1, is(tabState.entries[0].referrer, REFERRER1,
"Referrer retrieved via getTabState matches referrer set via loadURI."); "Referrer retrieved via getTabState matches referrer set via loadURI.");
tabState.entries[0].referrer = REFERRER2; tabState.entries[0].referrer = REFERRER2;

View File

@ -73,8 +73,7 @@ function test() {
try { try {
aFunction(); aFunction();
return false; return false;
} } catch (ex) {
catch (ex) {
return ex.name == "NS_ERROR_ILLEGAL_VALUE"; return ex.name == "NS_ERROR_ILLEGAL_VALUE";
} }
} }

View File

@ -12,13 +12,13 @@ function checkState(tab) {
let popStateCount = 0; let popStateCount = 0;
tab.linkedBrowser.addEventListener('popstate', function(aEvent) { tab.linkedBrowser.addEventListener("popstate", function(aEvent) {
let contentWindow = tab.linkedBrowser.contentWindow; let contentWindow = tab.linkedBrowser.contentWindow;
if (popStateCount == 0) { if (popStateCount == 0) {
popStateCount++; popStateCount++;
is(tab.linkedBrowser.contentWindow.testState, 'foo', is(tab.linkedBrowser.contentWindow.testState, "foo",
'testState after going back'); "testState after going back");
ok(aEvent.state, "Event should have a state property."); ok(aEvent.state, "Event should have a state property.");
is(JSON.stringify(tab.linkedBrowser.contentWindow.history.state), JSON.stringify({obj1:1}), is(JSON.stringify(tab.linkedBrowser.contentWindow.history.state), JSON.stringify({obj1:1}),
@ -33,8 +33,7 @@ function checkState(tab) {
doc.body.appendChild(elem); doc.body.appendChild(elem);
tab.linkedBrowser.goForward(); tab.linkedBrowser.goForward();
} } else if (popStateCount == 1) {
else if (popStateCount == 1) {
popStateCount++; popStateCount++;
// When content fires a PopStateEvent and we observe it from a chrome event // When content fires a PopStateEvent and we observe it from a chrome event
// listener (as we do here, and, thankfully, nowhere else in the tree), the // listener (as we do here, and, thankfully, nowhere else in the tree), the
@ -64,7 +63,7 @@ function checkState(tab) {
// Set some state in the page's window. When we go back(), the page should // Set some state in the page's window. When we go back(), the page should
// be retrieved from bfcache, and this state should still be there. // be retrieved from bfcache, and this state should still be there.
tab.linkedBrowser.contentWindow.testState = 'foo'; tab.linkedBrowser.contentWindow.testState = "foo";
// Now go back. This should trigger the popstate event handler above. // Now go back. This should trigger the popstate event handler above.
tab.linkedBrowser.goBack(); tab.linkedBrowser.goBack();

View File

@ -19,10 +19,10 @@ function test() {
} }
function getSessionstorejsModificationTime() { function getSessionstorejsModificationTime() {
let file = getSessionstoreFile(); let file = getSessionstoreFile();
if (file.exists()) if (file.exists()) {
return file.lastModifiedTime; return file.lastModifiedTime;
else }
return -1; return -1;
} }
// delete existing sessionstore.js, to make sure we're not reading // delete existing sessionstore.js, to make sure we're not reading
@ -49,7 +49,7 @@ function test() {
promiseBrowserLoaded(tab.linkedBrowser).then(() => { promiseBrowserLoaded(tab.linkedBrowser).then(() => {
// step1: the above has triggered some saveStateDelayed(), sleep until // step1: the above has triggered some saveStateDelayed(), sleep until
// it's done, and get the initial sessionstore.js mtime // it's done, and get the initial sessionstore.js mtime
setTimeout(function step1(e) { setTimeout(function step1() {
let mtime1 = getSessionstorejsModificationTime(); let mtime1 = getSessionstorejsModificationTime();
isnot(mtime1, mtime0, "initial sessionstore.js update"); isnot(mtime1, mtime0, "initial sessionstore.js update");
@ -57,7 +57,7 @@ function test() {
// or content scrolling // or content scrolling
gBrowser.selectedTab = tab; gBrowser.selectedTab = tab;
tab.linkedBrowser.contentWindow.scrollTo(1100, 1200); tab.linkedBrowser.contentWindow.scrollTo(1100, 1200);
setTimeout(function step2(e) { setTimeout(function step2() {
let mtime2 = getSessionstorejsModificationTime(); let mtime2 = getSessionstorejsModificationTime();
is(mtime2, mtime1, is(mtime2, mtime1,
"tab selection and scrolling: sessionstore.js not updated"); "tab selection and scrolling: sessionstore.js not updated");

View File

@ -19,8 +19,8 @@ function test() {
}; };
var theWin = openDialog(location, "", "chrome,all,dialog=no"); var theWin = openDialog(location, "", "chrome,all,dialog=no");
theWin.addEventListener("load", function () { theWin.addEventListener("load", function() {
executeSoon(function () { executeSoon(function() {
var gotError = false; var gotError = false;
try { try {
ss.setWindowState(theWin, JSON.stringify(state), true); ss.setWindowState(theWin, JSON.stringify(state), true);

View File

@ -145,7 +145,7 @@ function test() {
// be in a non-userTypedValue case, while others should still have // be in a non-userTypedValue case, while others should still have
// userTypedValue and userTypedClear set. // userTypedValue and userTypedClear set.
gBrowser.addTabsProgressListener({ gBrowser.addTabsProgressListener({
onLocationChange: function (aBrowser) { onLocationChange(aBrowser) {
if (uris.indexOf(aBrowser.currentURI.spec) > -1) { if (uris.indexOf(aBrowser.currentURI.spec) > -1) {
gBrowser.removeTabsProgressListener(this); gBrowser.removeTabsProgressListener(this);
firstLocationChange(); firstLocationChange();
@ -194,9 +194,9 @@ function test() {
let inputText = "example.org"; let inputText = "example.org";
gURLBar.focus(); gURLBar.focus();
gURLBar.value = inputText.slice(0, -1); gURLBar.value = inputText.slice(0, -1);
EventUtils.synthesizeKey(inputText.slice(-1) , {}); EventUtils.synthesizeKey(inputText.slice(-1), {});
executeSoon(function () { executeSoon(function() {
is(browser.userTypedValue, "example.org", is(browser.userTypedValue, "example.org",
"userTypedValue was set when changing URLBar value"); "userTypedValue was set when changing URLBar value");
ok(!browser.didStartLoadSinceLastUserTyping(), ok(!browser.didStartLoadSinceLastUserTyping(),

View File

@ -10,7 +10,7 @@ function test() {
waitForExplicitFinish(); waitForExplicitFinish();
whenNewWindowLoaded({ private: false }, function (window_B) { whenNewWindowLoaded({ private: false }, function(window_B) {
waitForFocus(function() { waitForFocus(function() {
// Add identifying information to window_B // Add identifying information to window_B
ss.setWindowValue(window_B, uniqKey, uniqVal); ss.setWindowValue(window_B, uniqKey, uniqVal);

View File

@ -53,12 +53,11 @@ function test() {
} else { } else {
info("waiting for the current window to become active"); info("waiting for the current window to become active");
setTimeout(pollMostRecentWindow, 0); setTimeout(pollMostRecentWindow, 0);
window.focus(); //XXX Why is this needed? window.focus(); // XXX Why is this needed?
} }
} }
pollMostRecentWindow(); pollMostRecentWindow();
} } else {
else {
browserWindowsCount(1); browserWindowsCount(1);
ok(!window.closed, "Restoring the old state should have left this window open"); ok(!window.closed, "Restoring the old state should have left this window open");
Services.obs.removeObserver(observer, "sessionstore-browser-state-restored"); Services.obs.removeObserver(observer, "sessionstore-browser-state-restored");

View File

@ -55,13 +55,13 @@ function openWinWithCb(cb, argURIs, expectedURIs) {
var win = openDialog(getBrowserURL(), "_blank", var win = openDialog(getBrowserURL(), "_blank",
"chrome,all,dialog=no", argURIs.join("|")); "chrome,all,dialog=no", argURIs.join("|"));
win.addEventListener("load", function () { win.addEventListener("load", function() {
info("the window loaded"); info("the window loaded");
var expectedLoads = expectedURIs.length; var expectedLoads = expectedURIs.length;
win.gBrowser.addTabsProgressListener({ win.gBrowser.addTabsProgressListener({
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) { onStateChange(aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
if (aRequest && if (aRequest &&
aStateFlags & Ci.nsIWebProgressListener.STATE_STOP && aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK && aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
@ -70,7 +70,7 @@ function openWinWithCb(cb, argURIs, expectedURIs) {
win.gBrowser.removeTabsProgressListener(this); win.gBrowser.removeTabsProgressListener(this);
info("all tabs loaded"); info("all tabs loaded");
is(win.gBrowser.tabs.length, expectedURIs.length, "didn't load any unexpected tabs"); is(win.gBrowser.tabs.length, expectedURIs.length, "didn't load any unexpected tabs");
executeSoon(function () { executeSoon(function() {
cb(win); cb(win);
}); });
} }

View File

@ -8,7 +8,7 @@ const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
add_task(function* test() { add_task(function* test() {
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, true); Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, true);
registerCleanupFunction(function () { registerCleanupFunction(function() {
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND); Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
}); });
@ -24,7 +24,7 @@ add_task(function* test() {
let loadCount = 0; let loadCount = 0;
let promiseRestoringTabs = new Promise(resolve => { let promiseRestoringTabs = new Promise(resolve => {
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) { gProgressListener.setCallback(function(aBrowser, aNeedRestore, aRestoring, aRestored) {
loadCount++; loadCount++;
// We'll make sure that the loads we get come from pinned tabs or the // We'll make sure that the loads we get come from pinned tabs or the

View File

@ -9,7 +9,7 @@ add_task(function* test() {
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, true); Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, true);
Services.prefs.setBoolPref(PREF_RESTORE_PINNED_TABS_ON_DEMAND, true); Services.prefs.setBoolPref(PREF_RESTORE_PINNED_TABS_ON_DEMAND, true);
registerCleanupFunction(function () { registerCleanupFunction(function() {
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND); Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
Services.prefs.clearUserPref(PREF_RESTORE_PINNED_TABS_ON_DEMAND); Services.prefs.clearUserPref(PREF_RESTORE_PINNED_TABS_ON_DEMAND);
}); });
@ -25,7 +25,7 @@ add_task(function* test() {
], selected: 5 }] }; ], selected: 5 }] };
let promiseRestoringTabs = new Promise(resolve => { let promiseRestoringTabs = new Promise(resolve => {
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) { gProgressListener.setCallback(function(aBrowser, aNeedRestore, aRestoring, aRestored) {
// get the tab // get the tab
let tab; let tab;
for (let i = 0; i < window.gBrowser.tabs.length; i++) { for (let i = 0; i < window.gBrowser.tabs.length; i++) {

View File

@ -8,7 +8,7 @@ requestLongerTimeout(2);
add_task(function* test() { add_task(function* test() {
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false); Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false);
registerCleanupFunction(function () { registerCleanupFunction(function() {
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND); Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
}); });
@ -63,7 +63,7 @@ add_task(function* test() {
let loadCount = 0; let loadCount = 0;
let promiseRestoringTabs = new Promise(resolve => { let promiseRestoringTabs = new Promise(resolve => {
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) { gProgressListener.setCallback(function(aBrowser, aNeedRestore, aRestoring, aRestored) {
loadCount++; loadCount++;
if (aBrowser.currentURI.spec == state1.windows[0].tabs[2].entries[0].url) if (aBrowser.currentURI.spec == state1.windows[0].tabs[2].entries[0].url)

View File

@ -6,7 +6,7 @@ const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
add_task(function* test() { add_task(function* test() {
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false); Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false);
registerCleanupFunction(function () { registerCleanupFunction(function() {
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND); Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
}); });
@ -30,7 +30,7 @@ add_task(function* test() {
let loadCount = 0; let loadCount = 0;
let promiseRestoringTabs = new Promise(resolve => { let promiseRestoringTabs = new Promise(resolve => {
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) { gProgressListener.setCallback(function(aBrowser, aNeedRestore, aRestoring, aRestored) {
loadCount++; loadCount++;
let expected = expectedCounts[loadCount - 1]; let expected = expectedCounts[loadCount - 1];

View File

@ -6,7 +6,7 @@ const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
add_task(function* test() { add_task(function* test() {
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false); Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false);
registerCleanupFunction(function () { registerCleanupFunction(function() {
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND); Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
}); });
@ -35,7 +35,7 @@ add_task(function* test() {
let loadCount = 0; let loadCount = 0;
let promiseRestoringTabs = new Promise(resolve => { let promiseRestoringTabs = new Promise(resolve => {
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) { gProgressListener.setCallback(function(aBrowser, aNeedRestore, aRestoring, aRestored) {
if (++loadCount == numTabs) { if (++loadCount == numTabs) {
// We don't actually care about load order in this test, just that they all // We don't actually care about load order in this test, just that they all
// do load. // do load.

View File

@ -6,7 +6,7 @@ const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
add_task(function* test() { add_task(function* test() {
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, true); Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, true);
registerCleanupFunction(function () { registerCleanupFunction(function() {
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND); Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
}); });

View File

@ -6,7 +6,7 @@ const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
add_task(function* test() { add_task(function* test() {
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, true); Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, true);
registerCleanupFunction(function () { registerCleanupFunction(function() {
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND); Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
}); });
@ -31,7 +31,7 @@ add_task(function* test() {
let loadCount = 0; let loadCount = 0;
let promiseRestoringTabs = new Promise(resolve => { let promiseRestoringTabs = new Promise(resolve => {
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) { gProgressListener.setCallback(function(aBrowser, aNeedRestore, aRestoring, aRestored) {
loadCount++; loadCount++;
let expected = expectedCounts[loadCount - 1]; let expected = expectedCounts[loadCount - 1];

View File

@ -6,7 +6,7 @@ const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
add_task(function* test() { add_task(function* test() {
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false); Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false);
registerCleanupFunction(function () { registerCleanupFunction(function() {
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND); Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
}); });
@ -30,7 +30,7 @@ add_task(function* test() {
let loadCount = 0; let loadCount = 0;
let promiseRestoringTabs = new Promise(resolve => { let promiseRestoringTabs = new Promise(resolve => {
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) { gProgressListener.setCallback(function(aBrowser, aNeedRestore, aRestoring, aRestored) {
// When loadCount == 2, we'll also restore state2 into the window // When loadCount == 2, we'll also restore state2 into the window
if (++loadCount == 2) { if (++loadCount == 2) {
ss.setWindowState(window, JSON.stringify(state2), false); ss.setWindowState(window, JSON.stringify(state2), false);

View File

@ -6,7 +6,7 @@ const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
add_task(function* test() { add_task(function* test() {
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false); Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false);
registerCleanupFunction(function () { registerCleanupFunction(function() {
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND); Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
}); });
@ -30,7 +30,7 @@ add_task(function* test() {
let loadCount = 0; let loadCount = 0;
let promiseRestoringTabs = new Promise(resolve => { let promiseRestoringTabs = new Promise(resolve => {
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) { gProgressListener.setCallback(function(aBrowser, aNeedRestore, aRestoring, aRestored) {
// When loadCount == 2, we'll also restore state2 into the window // When loadCount == 2, we'll also restore state2 into the window
if (++loadCount == 2) { if (++loadCount == 2) {
executeSoon(() => ss.setWindowState(window, JSON.stringify(state2), true)); executeSoon(() => ss.setWindowState(window, JSON.stringify(state2), true));

View File

@ -8,7 +8,7 @@ function observeOneRestore(callback) {
Services.obs.removeObserver(onRestore, topic); Services.obs.removeObserver(onRestore, topic);
callback(); callback();
}, topic, false); }, topic, false);
}; }
function test() { function test() {
waitForExplicitFinish(); waitForExplicitFinish();
@ -37,10 +37,10 @@ function test() {
observeOneRestore(function() { observeOneRestore(function() {
let testWindow = Services.wm.getEnumerator("navigator:browser").getNext(); let testWindow = Services.wm.getEnumerator("navigator:browser").getNext();
is(testWindow.gBrowser.visibleTabs.length, 1, "only restored 1 visible tab"); is(testWindow.gBrowser.visibleTabs.length, 1, "only restored 1 visible tab");
let tabs = testWindow.gBrowser.tabs; let restoredTabs = testWindow.gBrowser.tabs;
ok(!tabs[0].hidden, "first is still visible"); ok(!restoredTabs[0].hidden, "first is still visible");
ok(tabs[1].hidden, "second tab is still hidden"); ok(restoredTabs[1].hidden, "second tab is still hidden");
ok(tabs[2].hidden, "third tab is now hidden"); ok(restoredTabs[2].hidden, "third tab is now hidden");
// Restore the original state and clean up now that we're done // Restore the original state and clean up now that we're done
gBrowser.removeTab(hiddenTab); gBrowser.removeTab(hiddenTab);

View File

@ -9,7 +9,7 @@ function test() {
waitForExplicitFinish(); waitForExplicitFinish();
newWindowWithState(state, function (win) { newWindowWithState(state, function(win) {
registerCleanupFunction(() => BrowserTestUtils.closeWindow(win)); registerCleanupFunction(() => BrowserTestUtils.closeWindow(win));
is(win.gBrowser.tabs.length, 2, "two tabs were restored"); is(win.gBrowser.tabs.length, 2, "two tabs were restored");
@ -27,7 +27,7 @@ function newWindowWithState(state, callback) {
let win = window.openDialog(getBrowserURL(), "_blank", opts); let win = window.openDialog(getBrowserURL(), "_blank", opts);
win.addEventListener("load", function() { win.addEventListener("load", function() {
executeSoon(function () { executeSoon(function() {
win.addEventListener("SSWindowStateReady", function() { win.addEventListener("SSWindowStateReady", function() {
promiseTabRestored(win.gBrowser.tabs[0]).then(() => callback(win)); promiseTabRestored(win.gBrowser.tabs[0]).then(() => callback(win));
}, {once: true}); }, {once: true});

View File

@ -58,7 +58,7 @@ tests.push({
extra: false, extra: false,
close: false, close: false,
checkWinLin: checkNoWindowsGenerator(1), checkWinLin: checkNoWindowsGenerator(1),
checkOSX: function(aPreviousState, aCurState) { checkOSX(aPreviousState, aCurState) {
is(aCurState, aPreviousState, "test #1: closed window state is unchanged"); is(aCurState, aPreviousState, "test #1: closed window state is unchanged");
} }
}); });
@ -118,8 +118,7 @@ function test() {
function runNextTestOrFinish() { function runNextTestOrFinish() {
if (tests.length) { if (tests.length) {
setupForTest(tests.shift()) setupForTest(tests.shift())
} } else {
else {
// some state is cleaned up at the end of each test, but not all // some state is cleaned up at the end of each test, but not all
["browser.tabs.warnOnClose", "browser.startup.page"].forEach(function(p) { ["browser.tabs.warnOnClose", "browser.startup.page"].forEach(function(p) {
if (gPrefService.prefHasUserValue(p)) if (gPrefService.prefHasUserValue(p))
@ -166,7 +165,7 @@ function onStateRestored(aSubject, aTopic, aData) {
if (shouldPinTab) if (shouldPinTab)
newWin.gBrowser.pinTab(newWin.gBrowser.selectedTab); newWin.gBrowser.pinTab(newWin.gBrowser.selectedTab);
newWin.addEventListener("unload", function () { newWin.addEventListener("unload", function() {
onWindowUnloaded(); onWindowUnloaded();
}, {once: true}); }, {once: true});
// Open a new tab as well. On Windows/Linux this will be restored when the // Open a new tab as well. On Windows/Linux this will be restored when the
@ -179,15 +178,13 @@ function onStateRestored(aSubject, aTopic, aData) {
newTab.linkedBrowser.addEventListener("load", function() { newTab.linkedBrowser.addEventListener("load", function() {
if (shouldCloseTab == "one") { if (shouldCloseTab == "one") {
newWin.gBrowser.removeTab(newTab2); newWin.gBrowser.removeTab(newTab2);
} } else if (shouldCloseTab == "both") {
else if (shouldCloseTab == "both") {
newWin.gBrowser.removeTab(newTab); newWin.gBrowser.removeTab(newTab);
newWin.gBrowser.removeTab(newTab2); newWin.gBrowser.removeTab(newTab2);
} }
newWin.BrowserTryToCloseWindow(); newWin.BrowserTryToCloseWindow();
}, {capture: true, once: true}); }, {capture: true, once: true});
} } else {
else {
newWin.BrowserTryToCloseWindow(); newWin.BrowserTryToCloseWindow();
} }
}); });
@ -214,7 +211,7 @@ function onWindowUnloaded() {
// Now we want to open a new window // Now we want to open a new window
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no", "about:mozilla"); let newWin = openDialog(location, "_blank", "chrome,all,dialog=no", "about:mozilla");
newWin.addEventListener("load", function(aEvent) { newWin.addEventListener("load", function(aEvent) {
newWin.gBrowser.selectedBrowser.addEventListener("load", function () { newWin.gBrowser.selectedBrowser.addEventListener("load", function() {
// Good enough for checking the state // Good enough for checking the state
afterTestCallback(previousClosedWindowData, ss.getClosedWindowData()); afterTestCallback(previousClosedWindowData, ss.getClosedWindowData());
afterTestCleanup(newWin); afterTestCleanup(newWin);

View File

@ -11,8 +11,6 @@ function test() {
waitForExplicitFinish(); waitForExplicitFinish();
requestLongerTimeout(2); requestLongerTimeout(2);
let startedTest = false;
// wasLoaded will be used to keep track of tabs that have already had SSTabRestoring // wasLoaded will be used to keep track of tabs that have already had SSTabRestoring
// fired for them. // fired for them.
let wasLoaded = { }; let wasLoaded = { };
@ -87,8 +85,7 @@ function test() {
// then the test is successful. // then the test is successful.
try { try {
ss.deleteTabValue(tab, "baz"); ss.deleteTabValue(tab, "baz");
} } catch (e) {
catch (e) {
ok(false, "no error calling deleteTabValue - " + e); ok(false, "no error calling deleteTabValue - " + e);
} }

View File

@ -16,14 +16,14 @@ function test() {
waitForExplicitFinish(); waitForExplicitFinish();
newWindowWithState(state, function (win) { newWindowWithState(state, function(win) {
registerCleanupFunction(() => BrowserTestUtils.closeWindow(win)); registerCleanupFunction(() => BrowserTestUtils.closeWindow(win));
is(gBrowser.tabs.length, 1, "The total number of tabs should be 1"); is(gBrowser.tabs.length, 1, "The total number of tabs should be 1");
is(gBrowser.visibleTabs.length, 1, "The total number of visible tabs should be 1"); is(gBrowser.visibleTabs.length, 1, "The total number of visible tabs should be 1");
executeSoon(function () { executeSoon(function() {
waitForFocus(function () { waitForFocus(function() {
middleClickTest(win); middleClickTest(win);
finish(); finish();
}, win); }, win);
@ -64,7 +64,7 @@ function newWindowWithState(state, callback) {
callback(win); callback(win);
}, {capture: true, once: true}); }, {capture: true, once: true});
executeSoon(function () { executeSoon(function() {
ss.setWindowState(win, JSON.stringify(state), true); ss.setWindowState(win, JSON.stringify(state), true);
}); });
}, {once: true}); }, {once: true});

View File

@ -1,7 +1,7 @@
/* Any copyright is dedicated to the Public Domain. /* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */ http://creativecommons.org/publicdomain/zero/1.0/ */
var state = {windows:[{tabs:[ var windowState = {windows:[{tabs:[
{entries:[{url:"http://example.com#1", triggeringPrincipal_base64}]}, {entries:[{url:"http://example.com#1", triggeringPrincipal_base64}]},
{entries:[{url:"http://example.com#2", triggeringPrincipal_base64}]}, {entries:[{url:"http://example.com#2", triggeringPrincipal_base64}]},
{entries:[{url:"http://example.com#3", triggeringPrincipal_base64}]}, {entries:[{url:"http://example.com#3", triggeringPrincipal_base64}]},
@ -16,13 +16,13 @@ function test() {
waitForExplicitFinish(); waitForExplicitFinish();
requestLongerTimeout(2); requestLongerTimeout(2);
registerCleanupFunction(function () { registerCleanupFunction(function() {
Services.prefs.clearUserPref("browser.sessionstore.restore_hidden_tabs"); Services.prefs.clearUserPref("browser.sessionstore.restore_hidden_tabs");
}); });
// First stage: restoreHiddenTabs = true // First stage: restoreHiddenTabs = true
// Second stage: restoreHiddenTabs = false // Second stage: restoreHiddenTabs = false
test_loadTabs(true, function () { test_loadTabs(true, function() {
test_loadTabs(false, finish); test_loadTabs(false, finish);
}); });
} }
@ -33,7 +33,7 @@ function test_loadTabs(restoreHiddenTabs, callback) {
let expectedTabs = restoreHiddenTabs ? 8 : 4; let expectedTabs = restoreHiddenTabs ? 8 : 4;
let firstProgress = true; let firstProgress = true;
newWindowWithState(state, function (win, needsRestore, isRestoring) { newWindowWithState(windowState, function(win, needsRestore, isRestoring) {
if (firstProgress) { if (firstProgress) {
firstProgress = false; firstProgress = false;
is(isRestoring, 3, "restoring 3 tabs concurrently"); is(isRestoring, 3, "restoring 3 tabs concurrently");
@ -56,32 +56,32 @@ function test_loadTabs(restoreHiddenTabs, callback) {
} }
var TabsProgressListener = { var TabsProgressListener = {
init: function (win) { init(win) {
this.window = win; this.window = win;
Services.obs.addObserver(this, "sessionstore-debug-tab-restored", false); Services.obs.addObserver(this, "sessionstore-debug-tab-restored", false);
}, },
uninit: function () { uninit() {
Services.obs.removeObserver(this, "sessionstore-debug-tab-restored"); Services.obs.removeObserver(this, "sessionstore-debug-tab-restored");
delete this.window; delete this.window;
delete this.callback; delete this.callback;
}, },
setCallback: function (callback) { setCallback(callback) {
this.callback = callback; this.callback = callback;
}, },
observe: function (browser) { observe(browser) {
TabsProgressListener.onRestored(browser); TabsProgressListener.onRestored(browser);
}, },
onRestored: function (browser) { onRestored(browser) {
if (this.callback && browser.__SS_restoreState == TAB_STATE_RESTORING) if (this.callback && browser.__SS_restoreState == TAB_STATE_RESTORING)
this.callback.apply(null, [this.window].concat(this.countTabs())); this.callback.apply(null, [this.window].concat(this.countTabs()));
}, },
countTabs: function () { countTabs() {
let needsRestore = 0, isRestoring = 0; let needsRestore = 0, isRestoring = 0;
for (let i = 0; i < this.window.gBrowser.tabs.length; i++) { for (let i = 0; i < this.window.gBrowser.tabs.length; i++) {

View File

@ -5,7 +5,7 @@
* Bug 597071 - Closed windows should only be resurrected when there is a single * Bug 597071 - Closed windows should only be resurrected when there is a single
* popup window * popup window
*/ */
add_task(function test_close_last_nonpopup_window() { add_task(function* test_close_last_nonpopup_window() {
// Purge the list of closed windows. // Purge the list of closed windows.
forgetClosedWindows(); forgetClosedWindows();

View File

@ -74,13 +74,12 @@ function checkAutocompleteResults(aExpected, aCallback) {
searchParam: "enable-actions", searchParam: "enable-actions",
popupOpen: false, popupOpen: false,
minResultsForPopup: 0, minResultsForPopup: 0,
invalidate: function() {}, invalidate() {},
disableAutoComplete: false, disableAutoComplete: false,
completeDefaultIndex: false, completeDefaultIndex: false,
get popup() { return this; }, get popup() { return this; },
onSearchBegin: function() {}, onSearchBegin() {},
onSearchComplete: function () onSearchComplete() {
{
info("Found " + gController.matchCount + " matches."); info("Found " + gController.matchCount + " matches.");
// Check to see the expected uris and titles match up (in any order) // Check to see the expected uris and titles match up (in any order)
for (let i = 0; i < gController.matchCount; i++) { for (let i = 0; i < gController.matchCount; i++) {
@ -104,9 +103,9 @@ function checkAutocompleteResults(aExpected, aCallback) {
executeSoon(aCallback); executeSoon(aCallback);
}, },
setSelectedIndex: function() {}, setSelectedIndex() {},
get searchCount() { return this.searches.length; }, get searchCount() { return this.searches.length; },
getSearchAt: function(aIndex) { getSearchAt(aIndex) {
return this.searches[aIndex]; return this.searches[aIndex];
}, },
QueryInterface: XPCOMUtils.generateQI([ QueryInterface: XPCOMUtils.generateQI([

View File

@ -17,7 +17,7 @@ function testBug600545() {
Services.prefs.setBoolPref("browser.sessionstore.resume_from_crash", false); Services.prefs.setBoolPref("browser.sessionstore.resume_from_crash", false);
Services.prefs.setIntPref("browser.sessionstore.interval", 2000); Services.prefs.setIntPref("browser.sessionstore.interval", 2000);
registerCleanupFunction(function () { registerCleanupFunction(function() {
Services.prefs.clearUserPref("browser.sessionstore.resume_from_crash"); Services.prefs.clearUserPref("browser.sessionstore.resume_from_crash");
Services.prefs.clearUserPref("browser.sessionstore.interval"); Services.prefs.clearUserPref("browser.sessionstore.interval");
}); });
@ -51,7 +51,7 @@ function testBug600545() {
waitForBrowserState(state, function() { waitForBrowserState(state, function() {
// Need to wait for SessionStore's saveState function to be called // Need to wait for SessionStore's saveState function to be called
// so that non-pinned tabs will be stripped from non-active window // so that non-pinned tabs will be stripped from non-active window
waitForSaveState(function () { waitForSaveState(function() {
let expectedNumberOfTabs = getStateTabCount(state); let expectedNumberOfTabs = getStateTabCount(state);
let retrievedState = JSON.parse(ss.getBrowserState()); let retrievedState = JSON.parse(ss.getBrowserState());
let actualNumberOfTabs = getStateTabCount(retrievedState); let actualNumberOfTabs = getStateTabCount(retrievedState);

View File

@ -27,8 +27,7 @@ add_task(function* () {
if (tabState.extData) { if (tabState.extData) {
is(tabCurState.extData["uniq"], tabState.extData["uniq"], is(tabCurState.extData["uniq"], tabState.extData["uniq"],
"sanity check that tab has correct extData"); "sanity check that tab has correct extData");
} } else {
else {
// We aren't expecting there to be any data on extData, but panorama // We aren't expecting there to be any data on extData, but panorama
// may be setting something, so we need to make sure that if we do have // may be setting something, so we need to make sure that if we do have
// data, we just don't have anything for "uniq". // data, we just don't have anything for "uniq".
@ -64,8 +63,7 @@ add_task(function* () {
if ("extData" in tabState) { if ("extData" in tabState) {
ok(!("uniq" in tabState.extData), ok(!("uniq" in tabState.extData),
"(deleting) uniq not in existing extData"); "(deleting) uniq not in existing extData");
} } else {
else {
ok(true, "(deleting) no data is stored in extData"); ok(true, "(deleting) no data is stored in extData");
} }

View File

@ -74,8 +74,7 @@ function runNextTest() {
info("prepping for " + currentTest.name); info("prepping for " + currentTest.name);
waitForBrowserState(testState, currentTest); waitForBrowserState(testState, currentTest);
}); });
} } else {
else {
waitForBrowserState(stateBackup, finish); waitForBrowserState(stateBackup, finish);
} }
} }
@ -201,7 +200,7 @@ function test_undoCloseTab() {
function test_setWindowState() { function test_setWindowState() {
let testState = { let newState = {
windows: [{ windows: [{
tabs: [ tabs: [
{ entries: [{ url: "about:mozilla", triggeringPrincipal_base64 }], extData: { "foo": "bar" } }, { entries: [{ url: "about:mozilla", triggeringPrincipal_base64 }], extData: { "foo": "bar" } },
@ -244,7 +243,7 @@ function test_setWindowState() {
window.addEventListener("SSWindowStateReady", onSSWindowStateReady); window.addEventListener("SSWindowStateReady", onSSWindowStateReady);
gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored); gBrowser.tabContainer.addEventListener("SSTabRestored", onSSTabRestored);
ss.setWindowState(window, JSON.stringify(testState), true); ss.setWindowState(window, JSON.stringify(newState), true);
} }

View File

@ -40,8 +40,7 @@ function runNextTest() {
info("running " + currentTest.name); info("running " + currentTest.name);
waitForBrowserState(testState, currentTest); waitForBrowserState(testState, currentTest);
}); });
} } else {
else {
ss.setBrowserState(stateBackup); ss.setBrowserState(stateBackup);
executeSoon(finish); executeSoon(finish);
} }

View File

@ -2,18 +2,14 @@
http://creativecommons.org/publicdomain/zero/1.0/ */ http://creativecommons.org/publicdomain/zero/1.0/ */
function test() { function test() {
let assertNumberOfTabs = function (num, msg) { let assertNumberOfTabs = function(num, msg) {
is(gBrowser.tabs.length, num, msg); is(gBrowser.tabs.length, num, msg);
} }
let assertNumberOfVisibleTabs = function (num, msg) { let assertNumberOfVisibleTabs = function(num, msg) {
is(gBrowser.visibleTabs.length, num, msg); is(gBrowser.visibleTabs.length, num, msg);
} }
let assertNumberOfPinnedTabs = function (num, msg) {
is(gBrowser._numPinnedTabs, num, msg);
}
waitForExplicitFinish(); waitForExplicitFinish();
// check prerequisites // check prerequisites
@ -22,7 +18,7 @@ function test() {
// setup // setup
let tab = gBrowser.addTab("about:mozilla"); let tab = gBrowser.addTab("about:mozilla");
whenTabIsLoaded(tab, function () { whenTabIsLoaded(tab, function() {
// hide the newly created tab // hide the newly created tab
assertNumberOfVisibleTabs(2, "there are two visible tabs"); assertNumberOfVisibleTabs(2, "there are two visible tabs");
gBrowser.showOnlyTheseTabs([gBrowser.tabs[0]]); gBrowser.showOnlyTheseTabs([gBrowser.tabs[0]]);
@ -34,7 +30,7 @@ function test() {
tab = ss.undoCloseTab(window, 0); tab = ss.undoCloseTab(window, 0);
// check that everything was restored correctly, clean up and finish // check that everything was restored correctly, clean up and finish
whenTabIsLoaded(tab, function () { whenTabIsLoaded(tab, function() {
is(tab.linkedBrowser.currentURI.spec, "about:mozilla", "restored tab has correct url"); is(tab.linkedBrowser.currentURI.spec, "about:mozilla", "restored tab has correct url");
gBrowser.removeTab(tab); gBrowser.removeTab(tab);

View File

@ -17,7 +17,7 @@ var state = {windows:[{tabs:[
function test() { function test() {
waitForExplicitFinish(); waitForExplicitFinish();
registerCleanupFunction(function () { registerCleanupFunction(function() {
TabsProgressListener.uninit(); TabsProgressListener.uninit();
ss.setBrowserState(stateBackup); ss.setBrowserState(stateBackup);
}); });
@ -28,7 +28,7 @@ function test() {
window.addEventListener("SSWindowStateReady", function() { window.addEventListener("SSWindowStateReady", function() {
let firstProgress = true; let firstProgress = true;
TabsProgressListener.setCallback(function (needsRestore, isRestoring) { TabsProgressListener.setCallback(function(needsRestore, isRestoring) {
if (firstProgress) { if (firstProgress) {
firstProgress = false; firstProgress = false;
is(isRestoring, 3, "restoring 3 tabs concurrently"); is(isRestoring, 3, "restoring 3 tabs concurrently");
@ -70,28 +70,28 @@ function countTabs() {
} }
var TabsProgressListener = { var TabsProgressListener = {
init: function () { init() {
Services.obs.addObserver(this, "sessionstore-debug-tab-restored", false); Services.obs.addObserver(this, "sessionstore-debug-tab-restored", false);
}, },
uninit: function () { uninit() {
Services.obs.removeObserver(this, "sessionstore-debug-tab-restored"); Services.obs.removeObserver(this, "sessionstore-debug-tab-restored");
this.unsetCallback(); this.unsetCallback();
}, },
setCallback: function (callback) { setCallback(callback) {
this.callback = callback; this.callback = callback;
}, },
unsetCallback: function () { unsetCallback() {
delete this.callback; delete this.callback;
}, },
observe: function (browser, topic, data) { observe(browser, topic, data) {
TabsProgressListener.onRestored(browser); TabsProgressListener.onRestored(browser);
}, },
onRestored: function (browser) { onRestored(browser) {
if (this.callback && browser.__SS_restoreState == TAB_STATE_RESTORING) { if (this.callback && browser.__SS_restoreState == TAB_STATE_RESTORING) {
this.callback.apply(null, countTabs()); this.callback.apply(null, countTabs());
} }

View File

@ -14,12 +14,12 @@ const testState = {
}; };
// only finish() when correct number of windows opened // only finish() when correct number of windows opened
var restored = []; var restoredStates = [];
function addState(state) { function addState(state) {
restored.push(state); restoredStates.push(state);
if (restored.length == testState.scratchpads.length) { if (restoredStates.length == testState.scratchpads.length) {
ok(statesMatch(restored, testState.scratchpads), ok(statesMatch(restoredStates, testState.scratchpads),
"Two scratchpad windows restored"); "Two scratchpad windows restored");
Services.ww.unregisterNotification(windowObserver); Services.ww.unregisterNotification(windowObserver);
@ -41,7 +41,7 @@ function windowObserver(aSubject, aTopic, aData) {
win.addEventListener("load", function() { win.addEventListener("load", function() {
if (win.Scratchpad) { if (win.Scratchpad) {
win.Scratchpad.addObserver({ win.Scratchpad.addObserver({
onReady: function() { onReady() {
win.Scratchpad.removeObserver(this); win.Scratchpad.removeObserver(this);
let state = win.Scratchpad.getState(); let state = win.Scratchpad.getState();

View File

@ -14,7 +14,7 @@ function test() {
} }
Services.obs.addObserver(observe, NOTIFICATION, false); Services.obs.addObserver(observe, NOTIFICATION, false);
registerCleanupFunction(function () { registerCleanupFunction(function() {
Services.obs.removeObserver(observe, NOTIFICATION); Services.obs.removeObserver(observe, NOTIFICATION);
}); });

View File

@ -6,11 +6,11 @@ function test() {
let eventReceived = false; let eventReceived = false;
registerCleanupFunction(function () { registerCleanupFunction(function() {
ok(eventReceived, "SSWindowClosing event received"); ok(eventReceived, "SSWindowClosing event received");
}); });
newWindow(function (win) { newWindow(function(win) {
win.addEventListener("SSWindowClosing", function() { win.addEventListener("SSWindowClosing", function() {
eventReceived = true; eventReceived = true;
}, {once: true}); }, {once: true});

View File

@ -19,19 +19,19 @@ function test() {
// new format // new format
// index doesn't match value (testing an option in between (two)) // index doesn't match value (testing an option in between (two))
{ id:{ "select_id": {"selectedIndex":0,"value":"val2"} } }, { id:{ "select_id": {"selectedIndex":0, "value":"val2"} } },
// index doesn't match value (testing an invalid value) // index doesn't match value (testing an invalid value)
{ id:{ "select_id": {"selectedIndex":4,"value":"val8"} } }, { id:{ "select_id": {"selectedIndex":4, "value":"val8"} } },
// index doesn't match value (testing an invalid index) // index doesn't match value (testing an invalid index)
{ id:{ "select_id": {"selectedIndex":8,"value":"val5"} } }, { id:{ "select_id": {"selectedIndex":8, "value":"val5"} } },
// index and value match position zero // index and value match position zero
{ id:{ "select_id": {"selectedIndex":0,"value":"val0"} }, xpath: {} }, { id:{ "select_id": {"selectedIndex":0, "value":"val0"} }, xpath: {} },
// index doesn't match value (testing the last option (seven)) // index doesn't match value (testing the last option (seven))
{ id:{},"xpath":{ "/xhtml:html/xhtml:body/xhtml:select[@name='select_name']": {"selectedIndex":1,"value":"val7"} } }, { id:{}, "xpath":{ "/xhtml:html/xhtml:body/xhtml:select[@name='select_name']": {"selectedIndex":1, "value":"val7"} } },
// index and value match the default option "selectedIndex":3,"value":"val3" // index and value match the default option "selectedIndex":3,"value":"val3"
{ xpath: { "/xhtml:html/xhtml:body/xhtml:select[@name='select_name']" : {"selectedIndex":3,"value":"val3"} } }, { xpath: { "/xhtml:html/xhtml:body/xhtml:select[@name='select_name']" : {"selectedIndex":3, "value":"val3"} } },
// index matches default option however it doesn't match value // index matches default option however it doesn't match value
{ id:{ "select_id": {"selectedIndex":3,"value":"val4"} } }, { id:{ "select_id": {"selectedIndex":3, "value":"val4"} } },
]; ];
let expectedValues = [ let expectedValues = [

View File

@ -9,8 +9,8 @@ function test() {
ok(state.windows[0].busy, "window is busy"); ok(state.windows[0].busy, "window is busy");
window.addEventListener("SSWindowStateReady", function() { window.addEventListener("SSWindowStateReady", function() {
let state = JSON.parse(ss.getWindowState(window)); let state2 = JSON.parse(ss.getWindowState(window));
ok(!state.windows[0].busy, "window is not busy"); ok(!state2.windows[0].busy, "window is not busy");
executeSoon(() => { executeSoon(() => {
gBrowser.removeTab(gBrowser.tabs[1]); gBrowser.removeTab(gBrowser.tabs[1]);

View File

@ -38,7 +38,7 @@ var state = {windows:[{tabs:[{entries:[
]}]}]} ]}]}]}
function test() { function test() {
registerCleanupFunction(function () { registerCleanupFunction(function() {
ss.setBrowserState(stateBackup); ss.setBrowserState(stateBackup);
}); });

View File

@ -25,11 +25,10 @@ var state = {entries:[
} }
]}; ]};
function test() function test() {
{
waitForExplicitFinish(); waitForExplicitFinish();
registerCleanupFunction(function () { registerCleanupFunction(function() {
ss.setBrowserState(stateBackup); ss.setBrowserState(stateBackup);
}); });
@ -48,8 +47,7 @@ function test()
}); });
} }
function compareEntries(i, j, history) function compareEntries(i, j, history) {
{
let e1 = history.getEntryAtIndex(i, false) let e1 = history.getEntryAtIndex(i, false)
.QueryInterface(Ci.nsISHEntry) .QueryInterface(Ci.nsISHEntry)
.QueryInterface(Ci.nsISHContainer); .QueryInterface(Ci.nsISHContainer);
@ -59,15 +57,15 @@ function compareEntries(i, j, history)
.QueryInterface(Ci.nsISHContainer); .QueryInterface(Ci.nsISHContainer);
ok(e1.sharesDocumentWith(e2), ok(e1.sharesDocumentWith(e2),
i + ' should share doc with ' + j); i + " should share doc with " + j);
is(e1.childCount, e2.childCount, is(e1.childCount, e2.childCount,
'Child count mismatch (' + i + ', ' + j + ')'); "Child count mismatch (" + i + ", " + j + ")");
for (let c = 0; c < e1.childCount; c++) { for (let c = 0; c < e1.childCount; c++) {
let c1 = e1.GetChildAt(c); let c1 = e1.GetChildAt(c);
let c2 = e2.GetChildAt(c); let c2 = e2.GetChildAt(c);
ok(c1.sharesDocumentWith(c2), ok(c1.sharesDocumentWith(c2),
'Cousins should share documents. (' + i + ', ' + j + ', ' + c + ')'); "Cousins should share documents. (" + i + ", " + j + ", " + c + ")");
} }
} }

Some files were not shown because too many files have changed in this diff Show More