mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
Merge m-c to inbound, a=merge
MozReview-Commit-ID: AzYu7EXTIlg
This commit is contained in:
commit
0902d5e08e
@ -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/**
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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');
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
@ -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
|
||||||
|
@ -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]
|
||||||
|
@ -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");
|
||||||
|
});
|
@ -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();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
@ -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]
|
||||||
|
@ -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() {},
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
|
@ -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])
|
||||||
|
@ -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) || {};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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];
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
@ -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)) {
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
@ -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":
|
||||||
|
@ -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);
|
||||||
|
@ -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];
|
||||||
|
@ -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)) {
|
||||||
|
@ -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;
|
||||||
|
@ -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 ""; }
|
||||||
};
|
};
|
||||||
|
@ -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
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
},
|
},
|
||||||
|
@ -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);
|
||||||
});
|
});
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
});
|
});
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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;
|
||||||
});
|
});
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
});
|
});
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
});
|
});
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
|
@ -36,6 +36,6 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
frames[1].document.designMode = "on";
|
frames[1].document.designMode = "on";
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
@ -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";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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"}}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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");
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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");
|
||||||
|
|
||||||
|
@ -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";
|
||||||
}
|
}
|
||||||
|
@ -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"}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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");
|
||||||
|
@ -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);
|
||||||
|
@ -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(),
|
||||||
|
@ -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);
|
||||||
|
@ -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");
|
||||||
|
@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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++) {
|
||||||
|
@ -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)
|
||||||
|
@ -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];
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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];
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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));
|
||||||
|
@ -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);
|
||||||
|
@ -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});
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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});
|
||||||
|
@ -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++) {
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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([
|
||||||
|
@ -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);
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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});
|
||||||
|
@ -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 = [
|
||||||
|
@ -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]);
|
||||||
|
@ -38,7 +38,7 @@ var state = {windows:[{tabs:[{entries:[
|
|||||||
]}]}]}
|
]}]}]}
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
registerCleanupFunction(function () {
|
registerCleanupFunction(function() {
|
||||||
ss.setBrowserState(stateBackup);
|
ss.setBrowserState(stateBackup);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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
Loading…
Reference in New Issue
Block a user