зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to graphics
MozReview-Commit-ID: 6JFx7MHUHgW
This commit is contained in:
Коммит
5041aa0404
|
@ -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/newtab/**
|
||||
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/**
|
||||
# generated & special files in cld2
|
||||
browser/components/translation/cld2/**
|
||||
|
|
2
CLOBBER
2
CLOBBER
|
@ -22,4 +22,4 @@
|
|||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 1345336 - Crash in icu_58::TimeZoneFormat::initGMTOffsetPatterns
|
||||
Bug 1346967 - Generate metadata for all three ISimpleDOM interfaces via a single combined run of MIDL
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
* 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/. */
|
||||
|
||||
1 typelib ISimpleDOMNode.tlb
|
||||
1 typelib ISimpleDOM.tlb
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
// We use #include instead of import here so that MIDL treats these files as
|
||||
// part of the current file, thus forcing MIDL to generate proxy info for them.
|
||||
#include "ISimpleDOMNode.idl"
|
||||
#include "ISimpleDOMDocument.idl"
|
||||
#include "ISimpleDOMText.idl"
|
||||
|
||||
[
|
||||
uuid(a6245497-9c0b-4449-85a5-bd6ad07df8ea),
|
||||
helpstring("ISimpleDOM Type Library")
|
||||
]
|
||||
library ISimpleDOM
|
||||
{
|
||||
interface ISimpleDOMNode;
|
||||
interface ISimpleDOMText;
|
||||
interface ISimpleDOMDocument;
|
||||
};
|
||||
|
|
@ -99,9 +99,6 @@ cpp_quote("")
|
|||
import "objidl.idl";
|
||||
import "oaidl.idl";
|
||||
|
||||
import "ISimpleDOMText.idl";
|
||||
import "ISimpleDOMDocument.idl";
|
||||
|
||||
[object, uuid(1814ceeb-49e2-407f-af99-fa755a7d2607)]
|
||||
interface ISimpleDOMNode : IUnknown
|
||||
{
|
||||
|
@ -174,15 +171,3 @@ interface ISimpleDOMNode : IUnknown
|
|||
[propget] HRESULT language([out, retval] BSTR *language);
|
||||
}
|
||||
|
||||
|
||||
[
|
||||
uuid(a6245497-9c0b-4449-85a5-bd6ad07df8ea),
|
||||
helpstring("ISimpleDOM Type Library")
|
||||
]
|
||||
library ISimpleDOM
|
||||
{
|
||||
interface ISimpleDOMNode;
|
||||
interface ISimpleDOMText;
|
||||
interface ISimpleDOMDocument;
|
||||
};
|
||||
|
||||
|
|
|
@ -6,27 +6,20 @@ GARBAGE += $(MIDL_GENERATED_FILES) done_gen
|
|||
|
||||
MIDL_GENERATED_FILES = \
|
||||
dlldata.c \
|
||||
ISimpleDOMNode.h \
|
||||
ISimpleDOMNode_p.c \
|
||||
ISimpleDOMNode_i.c \
|
||||
ISimpleDOMNode.tlb \
|
||||
ISimpleDOMDocument.h \
|
||||
ISimpleDOMDocument_p.c \
|
||||
ISimpleDOMDocument_i.c \
|
||||
ISimpleDOMText.h \
|
||||
ISimpleDOMText_p.c \
|
||||
ISimpleDOMText_i.c \
|
||||
ISimpleDOM.h \
|
||||
ISimpleDOM_i.c \
|
||||
ISimpleDOM_p.c \
|
||||
ISimpleDOM.tlb \
|
||||
$(NULL)
|
||||
|
||||
$(MIDL_GENERATED_FILES): done_gen
|
||||
|
||||
done_gen: ISimpleDOMNode.idl \
|
||||
done_gen: ISimpleDOM.idl \
|
||||
ISimpleDOMNode.idl \
|
||||
ISimpleDOMDocument.idl \
|
||||
ISimpleDOMText.idl
|
||||
|
||||
$(MIDL) $(MIDL_FLAGS) -I $(srcdir) -Oicf $(srcdir)/ISimpleDOMNode.idl
|
||||
$(MIDL) $(MIDL_FLAGS) -Oicf $(srcdir)/ISimpleDOMDocument.idl
|
||||
$(MIDL) $(MIDL_FLAGS) -Oicf $(srcdir)/ISimpleDOMText.idl
|
||||
$(MIDL) $(MIDL_FLAGS) -I $(srcdir) -robust -Oicf $(srcdir)/ISimpleDOM.idl
|
||||
touch $@
|
||||
|
||||
export:: done_gen
|
||||
|
@ -38,12 +31,8 @@ register::
|
|||
EMBED_MANIFEST_AT = 2
|
||||
|
||||
midl_exports := \
|
||||
ISimpleDOMDocument.h \
|
||||
ISimpleDOMDocument_i.c \
|
||||
ISimpleDOMNode.h \
|
||||
ISimpleDOMNode_i.c \
|
||||
ISimpleDOMText.h \
|
||||
ISimpleDOMText_i.c \
|
||||
ISimpleDOM.h \
|
||||
ISimpleDOM_i.c \
|
||||
$(NULL)
|
||||
|
||||
INSTALL_TARGETS += midl_exports
|
||||
|
|
|
@ -8,15 +8,14 @@ GeckoSharedLibrary('AccessibleMarshal', linkage=None)
|
|||
|
||||
SOURCES += [
|
||||
'!dlldata.c',
|
||||
'!ISimpleDOMDocument_i.c',
|
||||
'!ISimpleDOMDocument_p.c',
|
||||
'!ISimpleDOMNode_i.c',
|
||||
'!ISimpleDOMNode_p.c',
|
||||
'!ISimpleDOMText_i.c',
|
||||
'!ISimpleDOMText_p.c',
|
||||
'!ISimpleDOM_i.c',
|
||||
'!ISimpleDOM_p.c',
|
||||
]
|
||||
|
||||
DEFINES['REGISTER_PROXY_DLL'] = True
|
||||
# The following line is required to preserve compatibility with older versions
|
||||
# of AccessibleMarshal.dll.
|
||||
DEFINES['PROXY_CLSID'] = 'IID_ISimpleDOMNode'
|
||||
|
||||
DEFFILE = SRCDIR + '/AccessibleMarshal.def'
|
||||
|
||||
|
@ -28,16 +27,10 @@ OS_LIBS += [
|
|||
|
||||
GENERATED_FILES += [
|
||||
'dlldata.c',
|
||||
'ISimpleDOMDocument.h',
|
||||
'ISimpleDOMDocument_i.c',
|
||||
'ISimpleDOMDocument_p.c',
|
||||
'ISimpleDOMNode.h',
|
||||
'ISimpleDOMNode.tlb',
|
||||
'ISimpleDOMNode_i.c',
|
||||
'ISimpleDOMNode_p.c',
|
||||
'ISimpleDOMText.h',
|
||||
'ISimpleDOMText_i.c',
|
||||
'ISimpleDOMText_p.c',
|
||||
'ISimpleDOM.h',
|
||||
'ISimpleDOM.tlb',
|
||||
'ISimpleDOM_i.c',
|
||||
'ISimpleDOM_p.c',
|
||||
]
|
||||
|
||||
RCINCLUDE = 'AccessibleMarshal.rc'
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "mozilla/Preferences.h"
|
||||
#include "nsIDocShell.h"
|
||||
|
||||
#include "ISimpleDOMNode_i.c"
|
||||
#include "ISimpleDOM.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "sdnAccessible-inl.h"
|
||||
#include "ISimpleDOMNode_i.c"
|
||||
#include "ISimpleDOM_i.c"
|
||||
|
||||
#include "DocAccessibleWrap.h"
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#ifndef mozilla_a11y_sdnAccessible_h_
|
||||
#define mozilla_a11y_sdnAccessible_h_
|
||||
|
||||
#include "ISimpleDOMNode.h"
|
||||
#include "ISimpleDOM.h"
|
||||
#include "AccessibleWrap.h"
|
||||
#include "IUnknownImpl.h"
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include "sdnDocAccessible.h"
|
||||
|
||||
#include "ISimpleDOMDocument_i.c"
|
||||
#include "ISimpleDOM.h"
|
||||
|
||||
#include "nsNameSpaceManager.h"
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#ifndef mozilla_a11y_sdnDocAccessible_h_
|
||||
#define mozilla_a11y_sdnDocAccessible_h_
|
||||
|
||||
#include "ISimpleDOMDocument.h"
|
||||
#include "ISimpleDOM.h"
|
||||
#include "IUnknownImpl.h"
|
||||
|
||||
#include "DocAccessibleWrap.h"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include "sdnTextAccessible.h"
|
||||
|
||||
#include "ISimpleDOMText_i.c"
|
||||
#include "ISimpleDOM.h"
|
||||
|
||||
#include "nsCoreUtils.h"
|
||||
#include "DocAccessible.h"
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#ifndef mozilla_a11y_sdnTextAccessible_h_
|
||||
#define mozilla_a11y_sdnTextAccessible_h_
|
||||
|
||||
#include "ISimpleDOMText.h"
|
||||
#include "ISimpleDOM.h"
|
||||
#include "IUnknownImpl.h"
|
||||
|
||||
#include "AccessibleWrap.h"
|
||||
|
|
|
@ -4,16 +4,6 @@
|
|||
'use strict'
|
||||
|
||||
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 { setTimeout } = require('sdk/timers');
|
||||
const { newURI } = require('sdk/url/utils');
|
||||
|
@ -41,7 +31,7 @@ exports.invalidResolve = invalidResolve;
|
|||
// Removes all children of group
|
||||
function clearBookmarks (group) {
|
||||
group
|
||||
? bmsrv.removeFolderChildren(group.id)
|
||||
? PlacesUtils.bookmarks.removeFolderChildren(group.id)
|
||||
: clearAllBookmarks();
|
||||
}
|
||||
|
||||
|
@ -65,12 +55,15 @@ exports.resetPlaces = resetPlaces;
|
|||
|
||||
function compareWithHost (assert, item) {
|
||||
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;
|
||||
|
||||
if (type === bmsrv.TYPE_BOOKMARK) {
|
||||
assert.equal(url, bmsrv.getBookmarkURI(id).spec.toString(), 'Matches host url');
|
||||
let tags = tagsrv.getTagsForURI(newURI(item.url));
|
||||
if (type === PlacesUtils.bookmarks.TYPE_BOOKMARK) {
|
||||
assert.equal(url, PlacesUtils.bookmarks.getBookmarkURI(id).spec.toString(),
|
||||
'Matches host url');
|
||||
let tags = PlacesUtils.tagging.getTagsForURI(newURI(item.url));
|
||||
for (let tag of tags) {
|
||||
// Handle both array for raw data and set for instances
|
||||
if (Array.isArray(item.tags))
|
||||
|
@ -82,45 +75,45 @@ function compareWithHost (assert, item) {
|
|||
Array.isArray(item.tags) ? item.tags.length : item.tags.size,
|
||||
'matches tag count');
|
||||
}
|
||||
if (type !== bmsrv.TYPE_SEPARATOR) {
|
||||
assert.equal(item.title, bmsrv.getItemTitle(id), 'Matches host title');
|
||||
if (type !== PlacesUtils.bookmarks.TYPE_SEPARATOR) {
|
||||
assert.equal(item.title, PlacesUtils.bookmarks.getItemTitle(id),
|
||||
'Matches host title');
|
||||
}
|
||||
assert.equal(item.index, bmsrv.getItemIndex(id), 'Matches host index');
|
||||
assert.equal(item.group.id || item.group, bmsrv.getFolderIdForItem(id), 'Matches host group id');
|
||||
assert.equal(type, bmsrv.getItemType(id), 'Matches host type');
|
||||
assert.equal(item.index, PlacesUtils.bookmarks.getItemIndex(id),
|
||||
'Matches host index');
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
var deferred = defer();
|
||||
asyncHistory.updatePlaces([].concat(urls).map(createVisit), {
|
||||
handleResult: function () {},
|
||||
handleError: deferred.reject,
|
||||
handleCompletion: deferred.resolve
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
return PlacesUtils.history.insertMany([].concat(urls).map(createVisit));
|
||||
}
|
||||
exports.addVisits = addVisits;
|
||||
|
||||
function removeVisits (urls) {
|
||||
[].concat(urls).map(url => {
|
||||
hsrv.removePage(newURI(url));
|
||||
});
|
||||
PlacesUtils.history.remove(urls);
|
||||
}
|
||||
exports.removeVisits = removeVisits;
|
||||
|
||||
// Creates a mozIVisitInfo object
|
||||
function createVisit (url) {
|
||||
let place = {}
|
||||
place.uri = newURI(url);
|
||||
place.title = "Test visit for " + place.uri.spec;
|
||||
place.visits = [{
|
||||
transitionType: hsrv.TRANSITION_LINK,
|
||||
visitDate: +(new Date()) * 1000,
|
||||
referredURI: undefined
|
||||
}];
|
||||
return place;
|
||||
return {
|
||||
url,
|
||||
title: "Test visit for " + url,
|
||||
visits: [{
|
||||
transition: PlacesUtils.history.TRANSITION_LINK
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
function createBookmark (data) {
|
||||
|
@ -141,7 +134,7 @@ function createBookmark (data) {
|
|||
exports.createBookmark = createBookmark;
|
||||
|
||||
function historyBatch () {
|
||||
hsrv.runInBatchMode(() => {}, null);
|
||||
PlacesUtils.history.runInBatchMode(() => {}, null);
|
||||
}
|
||||
exports.historyBatch = historyBatch;
|
||||
|
||||
|
|
|
@ -36,9 +36,9 @@ exports.testEmptyQuery = function*(assert) {
|
|||
'matches url');
|
||||
assert.equal(results[1].url, 'http://simplequery-2.com/',
|
||||
'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');
|
||||
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');
|
||||
assert.equal(results[0].visitCount, 1, 'matches access');
|
||||
assert.equal(results[1].visitCount, 1, 'matches access');
|
||||
|
|
|
@ -155,9 +155,13 @@ XPCOMUtils.defineLazyGetter(this, "PopupNotifications", function() {
|
|||
try {
|
||||
// Hide all notifications while the URL is being edited and the address bar
|
||||
// has focus, including the virtual focus in the results popup.
|
||||
// We also have to hide notifications explicitly when the window is
|
||||
// minimized because of the effects of the "noautohide" attribute on Linux.
|
||||
// This can be removed once bug 545265 and bug 1320361 are fixed.
|
||||
let shouldSuppress = () => {
|
||||
return gURLBar.getAttribute("pageproxystate") != "valid" &&
|
||||
gURLBar.focused;
|
||||
return window.windowState == window.STATE_MINIMIZED ||
|
||||
(gURLBar.getAttribute("pageproxystate") != "valid" &&
|
||||
gURLBar.focused);
|
||||
};
|
||||
return new tmp.PopupNotifications(gBrowser,
|
||||
document.getElementById("notification-popup"),
|
||||
|
@ -1500,6 +1504,15 @@ var gBrowserInit = {
|
|||
|
||||
gExtensionsNotifications.init();
|
||||
|
||||
let wasMinimized = window.windowState == window.STATE_MINIMIZED;
|
||||
window.addEventListener("sizemodechange", () => {
|
||||
let isMinimized = window.windowState == window.STATE_MINIMIZED;
|
||||
if (wasMinimized != isMinimized) {
|
||||
wasMinimized = isMinimized;
|
||||
UpdatePopupNotificationsVisibility();
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener("mousemove", MousePosTracker);
|
||||
window.addEventListener("dragover", MousePosTracker);
|
||||
|
||||
|
|
|
@ -6665,6 +6665,10 @@
|
|||
// Set the cursor to an arrow during tab drags.
|
||||
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.
|
||||
// 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
|
||||
|
|
|
@ -10,7 +10,7 @@ skip-if = (os == "linux" && debug) # linux: bug 976544
|
|||
[browser_devices_get_user_media_anim.js]
|
||||
[browser_devices_get_user_media_in_frame.js]
|
||||
[browser_devices_get_user_media_screen.js]
|
||||
skip-if = (e10s && debug) || (os == "linux" && !debug) # bug 1320754 for e10s debug, and bug 1320994 for linux opt
|
||||
skip-if = (e10s && debug) || (os == "linux") || (os == "win" && !debug) # bug 1320754 for e10s debug, and bug 1320994 for linux opt, bug 1338038 for windows and linux debug
|
||||
[browser_devices_get_user_media_tear_off_tab.js]
|
||||
[browser_devices_get_user_media_unprompted_access.js]
|
||||
[browser_devices_get_user_media_unprompted_access_in_frame.js]
|
||||
|
|
|
@ -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 browserAction chrome://browser/content/ext-browserAction.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 contextMenus chrome://browser/content/ext-contextMenus.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 browser_action chrome://browser/content/schemas/browser_action.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 context_menus chrome://browser/content/schemas/context_menus.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-browserAction.js
|
||||
content/browser/ext-browsingData.js
|
||||
content/browser/ext-chrome-settings-overrides.js
|
||||
content/browser/ext-commands.js
|
||||
content/browser/ext-contextMenus.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/browser_action.json
|
||||
content/browser/schemas/browsing_data.json
|
||||
content/browser/schemas/chrome_settings_overrides.json
|
||||
content/browser/schemas/commands.json
|
||||
content/browser/schemas/context_menus.json
|
||||
content/browser/schemas/context_menus_internal.json
|
||||
|
|
|
@ -120,6 +120,7 @@ support-files =
|
|||
[browser_ext_themes_icons.js]
|
||||
[browser_ext_topwindowid.js]
|
||||
[browser_ext_url_overrides_newtab.js]
|
||||
[browser_ext_url_overrides_home.js]
|
||||
[browser_ext_webRequest.js]
|
||||
[browser_ext_webNavigation_frameId0.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
|
||||
* awaitExtensionPanel awaitPopupResize
|
||||
* promiseContentDimensions alterContent
|
||||
* promisePrefChangeObserved
|
||||
*/
|
||||
|
||||
const {AppConstants} = Cu.import("resource://gre/modules/AppConstants.jsm", {});
|
||||
|
@ -348,3 +349,11 @@ function closePageAction(extension, win = window) {
|
|||
|
||||
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_favicon.js]
|
||||
[browser_privatebrowsing_geoprompt.js]
|
||||
tags = geolocation
|
||||
[browser_privatebrowsing_lastpbcontextexited.js]
|
||||
[browser_privatebrowsing_localStorage.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
|
||||
* network, finishCallback is called. Returns true if the load was successful.
|
||||
*/
|
||||
restoreTabContent: function (loadArguments, isRemotenessUpdate, finishCallback) {
|
||||
restoreTabContent(loadArguments, isRemotenessUpdate, finishCallback) {
|
||||
let tabData = this._tabData;
|
||||
this._tabData = null;
|
||||
|
||||
|
@ -199,7 +199,7 @@ ContentRestoreInternal.prototype = {
|
|||
// same state it was before the load started then trigger the load.
|
||||
let referrer = loadArguments.referrer ?
|
||||
Utils.makeURI(loadArguments.referrer) : null;
|
||||
let referrerPolicy = ('referrerPolicy' in loadArguments
|
||||
let referrerPolicy = ("referrerPolicy" in loadArguments
|
||||
? loadArguments.referrerPolicy
|
||||
: Ci.nsIHttpChannel.REFERRER_POLICY_UNSET);
|
||||
let postData = loadArguments.postData ?
|
||||
|
@ -243,11 +243,14 @@ ContentRestoreInternal.prototype = {
|
|||
}
|
||||
|
||||
return true;
|
||||
} catch (ex if ex instanceof Ci.nsIException) {
|
||||
// Ignore page load errors, but return false to signal that the load never
|
||||
// happened.
|
||||
return false;
|
||||
} catch (ex) {
|
||||
if (ex instanceof Ci.nsIException) {
|
||||
// Ignore page load errors, but return false to signal that the load never
|
||||
// happened.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -281,11 +284,11 @@ ContentRestoreInternal.prototype = {
|
|||
* position. The restore is complete when this function exits. It should be
|
||||
* called when the "load" event fires for the restoring tab.
|
||||
*/
|
||||
restoreDocument: function () {
|
||||
restoreDocument() {
|
||||
if (!this._restoringDocument) {
|
||||
return;
|
||||
}
|
||||
let {entry, pageStyle, formdata, scrollPositions} = this._restoringDocument;
|
||||
let {pageStyle, formdata, scrollPositions} = this._restoringDocument;
|
||||
this._restoringDocument = null;
|
||||
|
||||
let window = this.docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
|
@ -305,7 +308,7 @@ ContentRestoreInternal.prototype = {
|
|||
* case, it's called before restoreDocument, so it cannot clear
|
||||
* _restoringDocument.
|
||||
*/
|
||||
resetRestore: function () {
|
||||
resetRestore() {
|
||||
this._tabData = null;
|
||||
|
||||
if (this._historyListener) {
|
||||
|
@ -338,18 +341,18 @@ HistoryListener.prototype = {
|
|||
Ci.nsISupportsWeakReference
|
||||
]),
|
||||
|
||||
uninstall: function () {
|
||||
uninstall() {
|
||||
let shistory = this.webNavigation.sessionHistory;
|
||||
if (shistory) {
|
||||
shistory.removeSHistoryListener(this);
|
||||
}
|
||||
},
|
||||
|
||||
OnHistoryGoBack: function(backURI) { return true; },
|
||||
OnHistoryGoForward: function(forwardURI) { return true; },
|
||||
OnHistoryGotoIndex: function(index, gotoURI) { return true; },
|
||||
OnHistoryPurge: function(numEntries) { return true; },
|
||||
OnHistoryReplaceEntry: function(index) {},
|
||||
OnHistoryGoBack(backURI) { return true; },
|
||||
OnHistoryGoForward(forwardURI) { return true; },
|
||||
OnHistoryGotoIndex(index, gotoURI) { return true; },
|
||||
OnHistoryPurge(numEntries) { return true; },
|
||||
OnHistoryReplaceEntry(index) {},
|
||||
|
||||
// This will be called for a pending tab when loadURI(uri) is called where
|
||||
// the given |uri| only differs in the fragment.
|
||||
|
@ -408,11 +411,11 @@ ProgressListener.prototype = {
|
|||
Ci.nsISupportsWeakReference
|
||||
]),
|
||||
|
||||
uninstall: function() {
|
||||
uninstall() {
|
||||
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;
|
||||
if (!webProgress.isTopLevel || !(stateFlags & STATE_IS_WINDOW)) {
|
||||
return;
|
||||
|
@ -427,8 +430,8 @@ ProgressListener.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
onLocationChange: function() {},
|
||||
onProgressChange: function() {},
|
||||
onStatusChange: function() {},
|
||||
onSecurityChange: function() {},
|
||||
onLocationChange() {},
|
||||
onProgressChange() {},
|
||||
onStatusChange() {},
|
||||
onSecurityChange() {},
|
||||
};
|
||||
|
|
|
@ -10,11 +10,11 @@ this.EXPORTED_SYMBOLS = ["DocShellCapabilities"];
|
|||
* The external API exported by this module.
|
||||
*/
|
||||
this.DocShellCapabilities = Object.freeze({
|
||||
collect: function (docShell) {
|
||||
collect(docShell) {
|
||||
return DocShellCapabilitiesInternal.collect(docShell);
|
||||
},
|
||||
|
||||
restore: function (docShell, disallow) {
|
||||
restore(docShell, disallow) {
|
||||
return DocShellCapabilitiesInternal.restore(docShell, disallow);
|
||||
},
|
||||
});
|
||||
|
@ -29,7 +29,7 @@ var DocShellCapabilitiesInternal = {
|
|||
// properties.
|
||||
caps: null,
|
||||
|
||||
allCapabilities: function (docShell) {
|
||||
allCapabilities(docShell) {
|
||||
if (!this.caps) {
|
||||
let keys = Object.keys(docShell);
|
||||
this.caps = keys.filter(k => k.startsWith("allow")).map(k => k.slice(5));
|
||||
|
@ -37,12 +37,12 @@ var DocShellCapabilitiesInternal = {
|
|||
return this.caps;
|
||||
},
|
||||
|
||||
collect: function (docShell) {
|
||||
collect(docShell) {
|
||||
let caps = this.allCapabilities(docShell);
|
||||
return caps.filter(cap => !docShell["allow" + cap]);
|
||||
},
|
||||
|
||||
restore: function (docShell, disallow) {
|
||||
restore(docShell, disallow) {
|
||||
let caps = this.allCapabilities(docShell);
|
||||
for (let cap of caps)
|
||||
docShell["allow" + cap] = !disallow.has(cap);
|
||||
|
|
|
@ -80,7 +80,7 @@ FrameTreeInternal.prototype = {
|
|||
*
|
||||
* @param obs (object)
|
||||
*/
|
||||
addObserver: function (obs) {
|
||||
addObserver(obs) {
|
||||
this._observers.add(obs);
|
||||
},
|
||||
|
||||
|
@ -89,7 +89,7 @@ FrameTreeInternal.prototype = {
|
|||
*
|
||||
* @param method (string)
|
||||
*/
|
||||
notifyObservers: function (method) {
|
||||
notifyObservers(method) {
|
||||
for (let obs of this._observers) {
|
||||
if (obs.hasOwnProperty(method)) {
|
||||
obs[method]();
|
||||
|
@ -104,7 +104,7 @@ FrameTreeInternal.prototype = {
|
|||
* @param frame (nsIDOMWindow)
|
||||
* @return bool
|
||||
*/
|
||||
contains: function (frame) {
|
||||
contains(frame) {
|
||||
return this._frames.has(frame);
|
||||
},
|
||||
|
||||
|
@ -124,7 +124,7 @@ FrameTreeInternal.prototype = {
|
|||
* @param cb (function)
|
||||
* @return object
|
||||
*/
|
||||
map: function (cb) {
|
||||
map(cb) {
|
||||
let frames = this._frames;
|
||||
|
||||
function walk(frame) {
|
||||
|
@ -169,7 +169,7 @@ FrameTreeInternal.prototype = {
|
|||
* @param cb (function)
|
||||
* This callback receives the current frame as the only argument.
|
||||
*/
|
||||
forEach: function (cb) {
|
||||
forEach(cb) {
|
||||
let frames = this._frames;
|
||||
|
||||
function walk(frame) {
|
||||
|
@ -196,7 +196,7 @@ FrameTreeInternal.prototype = {
|
|||
* @param index (int)
|
||||
* 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.
|
||||
this._frames.set(frame, index);
|
||||
|
||||
|
@ -211,7 +211,7 @@ FrameTreeInternal.prototype = {
|
|||
* - new documents that start loading to clear the current frame tree;
|
||||
* - 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
|
||||
// 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.
|
||||
|
@ -244,10 +244,10 @@ FrameTreeInternal.prototype = {
|
|||
},
|
||||
|
||||
// Unused nsIWebProgressListener methods.
|
||||
onLocationChange: function () {},
|
||||
onProgressChange: function () {},
|
||||
onSecurityChange: function () {},
|
||||
onStatusChange: function () {},
|
||||
onLocationChange() {},
|
||||
onProgressChange() {},
|
||||
onSecurityChange() {},
|
||||
onStatusChange() {},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
|
||||
Ci.nsISupportsWeakReference])
|
||||
|
|
|
@ -28,14 +28,14 @@ GlobalStateInternal.prototype = {
|
|||
/**
|
||||
* Get all value from the global state.
|
||||
*/
|
||||
getState: function() {
|
||||
getState() {
|
||||
return this.state;
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear all currently stored global state.
|
||||
*/
|
||||
clear: function() {
|
||||
clear() {
|
||||
this.state = {};
|
||||
},
|
||||
|
||||
|
@ -46,7 +46,7 @@ GlobalStateInternal.prototype = {
|
|||
* A key the value is stored under.
|
||||
* @return The value stored at aKey, or an empty string if no value is set.
|
||||
*/
|
||||
get: function(aKey) {
|
||||
get(aKey) {
|
||||
return this.state[aKey] || "";
|
||||
},
|
||||
|
||||
|
@ -56,7 +56,7 @@ GlobalStateInternal.prototype = {
|
|||
* @param aKey
|
||||
* A key to store the value under.
|
||||
*/
|
||||
set: function(aKey, aStringValue) {
|
||||
set(aKey, aStringValue) {
|
||||
this.state[aKey] = aStringValue;
|
||||
},
|
||||
|
||||
|
@ -66,7 +66,7 @@ GlobalStateInternal.prototype = {
|
|||
* @param aKey
|
||||
* A key to delete the value for.
|
||||
*/
|
||||
delete: function(aKey) {
|
||||
delete(aKey) {
|
||||
delete this.state[aKey];
|
||||
},
|
||||
|
||||
|
@ -78,7 +78,7 @@ GlobalStateInternal.prototype = {
|
|||
* @param aState
|
||||
* A state object to extract global state from to be set.
|
||||
*/
|
||||
setFromState: function (aState) {
|
||||
setFromState(aState) {
|
||||
this.state = (aState && aState.global) || {};
|
||||
}
|
||||
};
|
||||
|
|
|
@ -12,11 +12,11 @@ const Ci = Components.interfaces;
|
|||
* The external API exported by this module.
|
||||
*/
|
||||
this.PageStyle = Object.freeze({
|
||||
collect: function (docShell, frameTree) {
|
||||
collect(docShell, frameTree) {
|
||||
return PageStyleInternal.collect(docShell, frameTree);
|
||||
},
|
||||
|
||||
restoreTree: function (docShell, data) {
|
||||
restoreTree(docShell, data) {
|
||||
PageStyleInternal.restoreTree(docShell, data);
|
||||
}
|
||||
});
|
||||
|
@ -28,7 +28,7 @@ var PageStyleInternal = {
|
|||
/**
|
||||
* Collects the selected style sheet sets for all reachable frames.
|
||||
*/
|
||||
collect: function (docShell, frameTree) {
|
||||
collect(docShell, frameTree) {
|
||||
let result = frameTree.map(({document: doc}) => {
|
||||
let style;
|
||||
|
||||
|
@ -71,23 +71,23 @@ var PageStyleInternal = {
|
|||
* ]
|
||||
* }
|
||||
*/
|
||||
restoreTree: function (docShell, data) {
|
||||
restoreTree(docShell, data) {
|
||||
let disabled = data.disabled || false;
|
||||
let markupDocumentViewer =
|
||||
docShell.contentViewer;
|
||||
markupDocumentViewer.authorStyleDisabled = disabled;
|
||||
|
||||
function restoreFrame(root, data) {
|
||||
if (data.hasOwnProperty("pageStyle")) {
|
||||
root.document.selectedStyleSheetSet = data.pageStyle;
|
||||
function restoreFrame(root, frameData) {
|
||||
if (frameData.hasOwnProperty("pageStyle")) {
|
||||
root.document.selectedStyleSheetSet = frameData.pageStyle;
|
||||
}
|
||||
|
||||
if (!data.hasOwnProperty("children")) {
|
||||
if (!frameData.hasOwnProperty("children")) {
|
||||
return;
|
||||
}
|
||||
|
||||
let frames = root.frames;
|
||||
data.children.forEach((child, index) => {
|
||||
frameData.children.forEach((child, index) => {
|
||||
if (child && index < frames.length) {
|
||||
restoreFrame(frames[index], child);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ this.PrivacyFilter = Object.freeze({
|
|||
* @param data The session storage data as collected from a tab.
|
||||
* @return object
|
||||
*/
|
||||
filterSessionStorageData: function (data) {
|
||||
filterSessionStorageData(data) {
|
||||
let retval = {};
|
||||
|
||||
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.
|
||||
* @return object
|
||||
*/
|
||||
filterFormData: function (data) {
|
||||
filterFormData(data) {
|
||||
// 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
|
||||
// children as well even if storing data for those frames would be allowed.
|
||||
if (data.url && !PrivacyLevel.check(data.url)) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
let retval = {};
|
||||
|
@ -81,7 +81,7 @@ this.PrivacyFilter = Object.freeze({
|
|||
* The browser state for which we remove any private windows and tabs.
|
||||
* The given object will be modified.
|
||||
*/
|
||||
filterPrivateWindowsAndTabs: function (browserState) {
|
||||
filterPrivateWindowsAndTabs(browserState) {
|
||||
// Remove private opened windows.
|
||||
for (let i = browserState.windows.length - 1; i >= 0; 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 given object will be modified.
|
||||
*/
|
||||
filterPrivateTabs: function (winState) {
|
||||
filterPrivateTabs(winState) {
|
||||
// Remove open private tabs.
|
||||
for (let i = winState.tabs.length - 1; i >= 0 ; i--) {
|
||||
let tab = winState.tabs[i];
|
||||
|
|
|
@ -37,8 +37,8 @@ this.RecentlyClosedTabsAndWindowsMenuUtils = {
|
|||
* Which localizable string to use for the 'restore all tabs' item.
|
||||
* @returns A document fragment with UI items for each recently closed tab.
|
||||
*/
|
||||
getTabsFragment: function(aWindow, aTagName, aPrefixRestoreAll=false,
|
||||
aRestoreAllLabel="menuRestoreAllTabs.label") {
|
||||
getTabsFragment(aWindow, aTagName, aPrefixRestoreAll = false,
|
||||
aRestoreAllLabel = "menuRestoreAllTabs.label") {
|
||||
let doc = aWindow.document;
|
||||
let fragment = doc.createDocumentFragment();
|
||||
if (SessionStore.getClosedTabCount(aWindow) != 0) {
|
||||
|
@ -67,8 +67,8 @@ this.RecentlyClosedTabsAndWindowsMenuUtils = {
|
|||
* Which localizable string to use for the 'restore all windows' item.
|
||||
* @returns A document fragment with UI items for each recently closed window.
|
||||
*/
|
||||
getWindowsFragment: function(aWindow, aTagName, aPrefixRestoreAll=false,
|
||||
aRestoreAllLabel="menuRestoreAllWindows.label") {
|
||||
getWindowsFragment(aWindow, aTagName, aPrefixRestoreAll = false,
|
||||
aRestoreAllLabel = "menuRestoreAllWindows.label") {
|
||||
let closedWindowData = SessionStore.getClosedWindowData(false);
|
||||
let doc = aWindow.document;
|
||||
let fragment = doc.createDocumentFragment();
|
||||
|
@ -104,7 +104,7 @@ this.RecentlyClosedTabsAndWindowsMenuUtils = {
|
|||
* @param aEvent
|
||||
* The event when the user clicks the menu item
|
||||
*/
|
||||
_undoCloseMiddleClick: function(aEvent) {
|
||||
_undoCloseMiddleClick(aEvent) {
|
||||
if (aEvent.button != 1)
|
||||
return;
|
||||
|
||||
|
@ -172,7 +172,7 @@ function createEntry(aTagName, aIsWindowsFragment, aIndex, aClosedTab,
|
|||
element.addEventListener("click", RecentlyClosedTabsAndWindowsMenuUtils._undoCloseMiddleClick);
|
||||
}
|
||||
if (aIndex == 0) {
|
||||
element.setAttribute("key", "key_undoClose" + (aIsWindowsFragment? "Window" : "Tab"));
|
||||
element.setAttribute("key", "key_undoClose" + (aIsWindowsFragment ? "Window" : "Tab"));
|
||||
}
|
||||
|
||||
aFragment.appendChild(element);
|
||||
|
@ -204,11 +204,11 @@ function createRestoreAllEntry(aDocument, aFragment, aPrefixRestoreAll,
|
|||
restoreAllElements.setAttribute("label", navigatorBundle.GetStringFromName(aRestoreAllLabel));
|
||||
restoreAllElements.setAttribute("oncommand",
|
||||
"for (var i = 0; i < " + aEntryCount + "; i++) undoClose" +
|
||||
(aIsWindowsFragment? "Window" : "Tab") + "();");
|
||||
(aIsWindowsFragment ? "Window" : "Tab") + "();");
|
||||
if (aPrefixRestoreAll) {
|
||||
aFragment.insertBefore(restoreAllElements, aFragment.firstChild);
|
||||
} else {
|
||||
aFragment.appendChild(aDocument.createElementNS(kNSXUL, "menuseparator"));
|
||||
aFragment.appendChild(restoreAllElements);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,11 +24,11 @@ const MAX_EXPIRY = Math.pow(2, 62);
|
|||
* The external API implemented by the SessionCookies module.
|
||||
*/
|
||||
this.SessionCookies = Object.freeze({
|
||||
update: function (windows) {
|
||||
update(windows) {
|
||||
SessionCookiesInternal.update(windows);
|
||||
},
|
||||
|
||||
getHostsForWindow: function (window, checkPrivacy = false) {
|
||||
getHostsForWindow(window, checkPrivacy = false) {
|
||||
return SessionCookiesInternal.getHostsForWindow(window, checkPrivacy);
|
||||
},
|
||||
|
||||
|
@ -55,7 +55,7 @@ var SessionCookiesInternal = {
|
|||
* Array of window state objects.
|
||||
* [{ tabs: [...], cookies: [...] }, ...]
|
||||
*/
|
||||
update: function (windows) {
|
||||
update(windows) {
|
||||
this._ensureInitialized();
|
||||
|
||||
for (let window of windows) {
|
||||
|
@ -71,7 +71,7 @@ var SessionCookiesInternal = {
|
|||
// _getCookiesForHost() will only return hosts with the right privacy
|
||||
// rules, so there is no need to do anything special with this call
|
||||
// to PrivacyLevel.canSave().
|
||||
if (PrivacyLevel.canSave({isHttps: cookie.secure, isPinned: isPinned})) {
|
||||
if (PrivacyLevel.canSave({isHttps: cookie.secure, isPinned})) {
|
||||
cookies.push(cookie);
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ var SessionCookiesInternal = {
|
|||
* whether we will use the deferred privacy level when
|
||||
* checking how much data to save on quitting.
|
||||
*/
|
||||
getHostsForWindow: function (window, checkPrivacy = false) {
|
||||
getHostsForWindow(window, checkPrivacy = false) {
|
||||
let hosts = {};
|
||||
|
||||
for (let tab of window.tabs) {
|
||||
|
@ -135,7 +135,7 @@ var SessionCookiesInternal = {
|
|||
* Handles observers notifications that are sent whenever cookies are added,
|
||||
* changed, or removed. Ensures that the storage is updated accordingly.
|
||||
*/
|
||||
observe: function (subject, topic, data) {
|
||||
observe(subject, topic, data) {
|
||||
switch (data) {
|
||||
case "added":
|
||||
case "changed":
|
||||
|
@ -163,7 +163,7 @@ var SessionCookiesInternal = {
|
|||
* 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.
|
||||
*/
|
||||
_ensureInitialized: function () {
|
||||
_ensureInitialized() {
|
||||
if (!this._initialized) {
|
||||
this._reloadCookies();
|
||||
this._initialized = true;
|
||||
|
@ -185,7 +185,7 @@ var SessionCookiesInternal = {
|
|||
* is the entry we're evaluating for a pinned tab; used only if
|
||||
* checkPrivacy
|
||||
*/
|
||||
_extractHostsFromEntry: function (entry, hosts, checkPrivacy, isPinned) {
|
||||
_extractHostsFromEntry(entry, hosts, checkPrivacy, isPinned) {
|
||||
let host = entry._host;
|
||||
let scheme = entry._scheme;
|
||||
|
||||
|
@ -199,8 +199,7 @@ var SessionCookiesInternal = {
|
|||
host = uri.host;
|
||||
scheme = uri.scheme;
|
||||
this._extractHostsFromHostScheme(host, scheme, hosts, checkPrivacy, isPinned);
|
||||
}
|
||||
catch (ex) { }
|
||||
} catch (ex) { }
|
||||
}
|
||||
|
||||
if (entry.children) {
|
||||
|
@ -226,13 +225,12 @@ var SessionCookiesInternal = {
|
|||
* is the entry we're evaluating for a pinned tab; used only if
|
||||
* checkPrivacy
|
||||
*/
|
||||
_extractHostsFromHostScheme:
|
||||
function (host, scheme, hosts, checkPrivacy, isPinned) {
|
||||
_extractHostsFromHostScheme(host, scheme, hosts, checkPrivacy, isPinned) {
|
||||
// host and scheme may not be set (for about: urls for example), in which
|
||||
// case testing scheme will be sufficient.
|
||||
if (/https?/.test(scheme) && !hosts[host] &&
|
||||
(!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
|
||||
// the host in update() if we should check for privacy.
|
||||
hosts[host] = isPinned;
|
||||
|
@ -244,7 +242,7 @@ var SessionCookiesInternal = {
|
|||
/**
|
||||
* Updates or adds a given cookie to the store.
|
||||
*/
|
||||
_updateCookie: function (cookie) {
|
||||
_updateCookie(cookie) {
|
||||
cookie.QueryInterface(Ci.nsICookie2);
|
||||
|
||||
if (cookie.isSession) {
|
||||
|
@ -257,7 +255,7 @@ var SessionCookiesInternal = {
|
|||
/**
|
||||
* Removes a given cookie from the store.
|
||||
*/
|
||||
_removeCookie: function (cookie) {
|
||||
_removeCookie(cookie) {
|
||||
cookie.QueryInterface(Ci.nsICookie2);
|
||||
|
||||
if (cookie.isSession) {
|
||||
|
@ -268,7 +266,7 @@ var SessionCookiesInternal = {
|
|||
/**
|
||||
* Removes a given list of cookies from the store.
|
||||
*/
|
||||
_removeCookies: function (cookies) {
|
||||
_removeCookies(cookies) {
|
||||
for (let i = 0; i < cookies.length; i++) {
|
||||
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
|
||||
* if they're session cookies.
|
||||
*/
|
||||
_reloadCookies: function () {
|
||||
_reloadCookies() {
|
||||
let iter = Services.cookies.enumerator;
|
||||
while (iter.hasMoreElements()) {
|
||||
this._updateCookie(iter.getNext());
|
||||
|
@ -358,10 +356,10 @@ var CookieStore = {
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
getCookiesForHost: function (host) {
|
||||
getCookiesForHost(mainHost) {
|
||||
let cookies = [];
|
||||
|
||||
let appendCookiesForHost = host => {
|
||||
|
@ -383,7 +381,7 @@ var CookieStore = {
|
|||
// <.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
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
@ -396,7 +394,7 @@ var CookieStore = {
|
|||
* @param cookie
|
||||
* The nsICookie2 object to add to the storage.
|
||||
*/
|
||||
set: function (cookie) {
|
||||
set(cookie) {
|
||||
let jscookie = {host: cookie.host, value: cookie.value};
|
||||
|
||||
// Only add properties with non-default values to save a few bytes.
|
||||
|
@ -433,14 +431,14 @@ var CookieStore = {
|
|||
* @param cookie
|
||||
* The nsICookie2 object to be removed from storage.
|
||||
*/
|
||||
delete: function (cookie) {
|
||||
delete(cookie) {
|
||||
this._ensureMap(cookie).delete(cookie.name);
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes all cookies.
|
||||
*/
|
||||
clear: function () {
|
||||
clear() {
|
||||
this._hosts.clear();
|
||||
},
|
||||
|
||||
|
@ -453,7 +451,7 @@ var CookieStore = {
|
|||
* @return The newly created Map instance mapping cookie names to
|
||||
* internal jscookies, in the given path of the given host.
|
||||
*/
|
||||
_ensureMap: function (cookie) {
|
||||
_ensureMap(cookie) {
|
||||
if (!this._hosts.has(cookie.host)) {
|
||||
this._hosts.set(cookie.host, new Map());
|
||||
}
|
||||
|
|
|
@ -66,19 +66,19 @@ this.SessionFile = {
|
|||
/**
|
||||
* Read the contents of the session file, asynchronously.
|
||||
*/
|
||||
read: function () {
|
||||
read() {
|
||||
return SessionFileInternal.read();
|
||||
},
|
||||
/**
|
||||
* Write the contents of the session file, asynchronously.
|
||||
*/
|
||||
write: function (aData) {
|
||||
write(aData) {
|
||||
return SessionFileInternal.write(aData);
|
||||
},
|
||||
/**
|
||||
* Wipe the contents of the session file, asynchronously.
|
||||
*/
|
||||
wipe: function () {
|
||||
wipe() {
|
||||
return SessionFileInternal.wipe();
|
||||
},
|
||||
|
||||
|
@ -226,32 +226,34 @@ var SessionFileInternal = {
|
|||
let source = yield OS.File.read(path, { encoding: "utf-8" });
|
||||
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.
|
||||
Cu.reportError("Cannot extract data from Session Restore file " + path + ". Wrong format/version: " + JSON.stringify(parsed.version) + ".");
|
||||
continue;
|
||||
}
|
||||
result = {
|
||||
origin: key,
|
||||
source: source,
|
||||
parsed: parsed
|
||||
source,
|
||||
parsed
|
||||
};
|
||||
Telemetry.getHistogramById("FX_SESSION_RESTORE_CORRUPT_FILE").
|
||||
add(false);
|
||||
Telemetry.getHistogramById("FX_SESSION_RESTORE_READ_FILE_MS").
|
||||
add(Date.now() - startMs);
|
||||
break;
|
||||
} catch (ex if ex instanceof OS.File.Error && ex.becauseNoSuchFile) {
|
||||
exists = false;
|
||||
} catch (ex if ex instanceof OS.File.Error) {
|
||||
// The file might be inaccessible due to wrong permissions
|
||||
// or similar failures. We'll just count it as "corrupted".
|
||||
console.error("Could not read session file ", ex, ex.stack);
|
||||
corrupted = true;
|
||||
} catch (ex if ex instanceof SyntaxError) {
|
||||
console.error("Corrupt session file (invalid JSON found) ", ex, ex.stack);
|
||||
// File is corrupted, try next file
|
||||
corrupted = true;
|
||||
} catch (ex) {
|
||||
if (ex instanceof OS.File.Error && ex.becauseNoSuchFile) {
|
||||
exists = false;
|
||||
} else if (ex instanceof OS.File.Error) {
|
||||
// The file might be inaccessible due to wrong permissions
|
||||
// or similar failures. We'll just count it as "corrupted".
|
||||
console.error("Could not read session file ", ex, ex.stack);
|
||||
corrupted = true;
|
||||
} else if (ex instanceof SyntaxError) {
|
||||
console.error("Corrupt session file (invalid JSON found) ", ex, ex.stack);
|
||||
// File is corrupted, try next file
|
||||
corrupted = true;
|
||||
}
|
||||
} finally {
|
||||
if (exists) {
|
||||
noFilesFound = false;
|
||||
|
@ -310,7 +312,7 @@ var SessionFileInternal = {
|
|||
return SessionWorker.post(...args)
|
||||
}),
|
||||
|
||||
write: function (aData) {
|
||||
write(aData) {
|
||||
if (RunState.isClosed) {
|
||||
return Promise.reject(new Error("SessionFile is closed"));
|
||||
}
|
||||
|
@ -377,12 +379,12 @@ var SessionFileInternal = {
|
|||
});
|
||||
},
|
||||
|
||||
wipe: function () {
|
||||
wipe() {
|
||||
return this._postToWorker("wipe");
|
||||
},
|
||||
|
||||
_recordTelemetry: function(telemetry) {
|
||||
for (let id of Object.keys(telemetry)){
|
||||
_recordTelemetry(telemetry) {
|
||||
for (let id of Object.keys(telemetry)) {
|
||||
let value = telemetry[id];
|
||||
let samples = [];
|
||||
if (Array.isArray(value)) {
|
||||
|
|
|
@ -15,12 +15,12 @@ XPCOMUtils.defineLazyModuleGetter(this, "Utils",
|
|||
"resource://gre/modules/sessionstore/Utils.jsm");
|
||||
|
||||
// An encoder to UTF-8.
|
||||
XPCOMUtils.defineLazyGetter(this, "gEncoder", function () {
|
||||
XPCOMUtils.defineLazyGetter(this, "gEncoder", function() {
|
||||
return new TextEncoder();
|
||||
});
|
||||
|
||||
// A decoder.
|
||||
XPCOMUtils.defineLazyGetter(this, "gDecoder", function () {
|
||||
XPCOMUtils.defineLazyGetter(this, "gDecoder", function() {
|
||||
return new TextDecoder();
|
||||
});
|
||||
|
||||
|
@ -39,7 +39,7 @@ var SessionMigrationInternal = {
|
|||
* The complete state is then wrapped into the "about:welcomeback" page as
|
||||
* form field info to be restored when restoring the state.
|
||||
*/
|
||||
convertState: function(aStateObj) {
|
||||
convertState(aStateObj) {
|
||||
let state = {
|
||||
selectedWindow: aStateObj.selectedWindow,
|
||||
_closedWindows: []
|
||||
|
@ -71,7 +71,7 @@ var SessionMigrationInternal = {
|
|||
/**
|
||||
* Asynchronously read session restore state (JSON) from a path
|
||||
*/
|
||||
readState: function(aPath) {
|
||||
readState(aPath) {
|
||||
return Task.spawn(function*() {
|
||||
let bytes = yield OS.File.read(aPath);
|
||||
let text = gDecoder.decode(bytes);
|
||||
|
@ -82,7 +82,7 @@ var SessionMigrationInternal = {
|
|||
/**
|
||||
* Asynchronously write session restore state as JSON to a path
|
||||
*/
|
||||
writeState: function(aPath, aState) {
|
||||
writeState(aPath, aState) {
|
||||
let bytes = gEncoder.encode(JSON.stringify(aState));
|
||||
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: function(aFromPath, aToPath) {
|
||||
migrate(aFromPath, aToPath) {
|
||||
return Task.spawn(function*() {
|
||||
let inState = yield SessionMigrationInternal.readState(aFromPath);
|
||||
let outState = SessionMigrationInternal.convertState(inState);
|
||||
|
|
|
@ -31,7 +31,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
|||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
|
||||
// Minimal interval between two save operations (in milliseconds).
|
||||
XPCOMUtils.defineLazyGetter(this, "gInterval", function () {
|
||||
XPCOMUtils.defineLazyGetter(this, "gInterval", function() {
|
||||
const PREF = "browser.sessionstore.interval";
|
||||
|
||||
// Observer that updates the cached value when the preference changes.
|
||||
|
@ -54,7 +54,7 @@ function notify(subject, topic) {
|
|||
|
||||
// TelemetryStopwatch helper functions.
|
||||
function stopWatch(method) {
|
||||
return function (...histograms) {
|
||||
return function(...histograms) {
|
||||
for (let hist of histograms) {
|
||||
TelemetryStopwatch[method]("FX_SESSION_RESTORE_" + hist);
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ this.SessionSaver = Object.freeze({
|
|||
/**
|
||||
* Immediately saves the current session to disk.
|
||||
*/
|
||||
run: function () {
|
||||
run() {
|
||||
return SessionSaverInternal.run();
|
||||
},
|
||||
|
||||
|
@ -81,7 +81,7 @@ this.SessionSaver = Object.freeze({
|
|||
* another delayed run be scheduled already, we will ignore the given delay
|
||||
* and state saving may occur a little earlier.
|
||||
*/
|
||||
runDelayed: function () {
|
||||
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
|
||||
* at least the configured interval when runDelayed() is called next.
|
||||
*/
|
||||
updateLastSaveTime: function () {
|
||||
updateLastSaveTime() {
|
||||
SessionSaverInternal.updateLastSaveTime();
|
||||
},
|
||||
|
||||
/**
|
||||
* Cancels all pending session saves.
|
||||
*/
|
||||
cancel: function () {
|
||||
cancel() {
|
||||
SessionSaverInternal.cancel();
|
||||
}
|
||||
});
|
||||
|
@ -121,7 +121,7 @@ var SessionSaverInternal = {
|
|||
/**
|
||||
* Immediately saves the current session to disk.
|
||||
*/
|
||||
run: function () {
|
||||
run() {
|
||||
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
|
||||
* save the current session.
|
||||
*/
|
||||
runDelayed: function (delay = 2000) {
|
||||
runDelayed(delay = 2000) {
|
||||
// Bail out if there's a pending run.
|
||||
if (this._timeoutID) {
|
||||
return;
|
||||
|
@ -151,14 +151,14 @@ var SessionSaverInternal = {
|
|||
* 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.
|
||||
*/
|
||||
updateLastSaveTime: function () {
|
||||
updateLastSaveTime() {
|
||||
this._lastSaveTime = Date.now();
|
||||
},
|
||||
|
||||
/**
|
||||
* Cancels all pending session saves.
|
||||
*/
|
||||
cancel: function () {
|
||||
cancel() {
|
||||
clearTimeout(this._timeoutID);
|
||||
this._timeoutID = null;
|
||||
},
|
||||
|
@ -170,7 +170,7 @@ var SessionSaverInternal = {
|
|||
* Forces us to recollect data for all windows and will bypass and
|
||||
* update the corresponding caches.
|
||||
*/
|
||||
_saveState: function (forceUpdateAllWindows = false) {
|
||||
_saveState(forceUpdateAllWindows = false) {
|
||||
// Cancel any pending timeouts.
|
||||
this.cancel();
|
||||
|
||||
|
@ -241,7 +241,7 @@ var SessionSaverInternal = {
|
|||
* _saveState() to collect data again (with a cache hit rate of hopefully
|
||||
* 100%) and write to disk afterwards.
|
||||
*/
|
||||
_saveStateAsync: function () {
|
||||
_saveStateAsync() {
|
||||
// Allow scheduling delayed saves again.
|
||||
this._timeoutID = null;
|
||||
|
||||
|
@ -252,7 +252,7 @@ var SessionSaverInternal = {
|
|||
/**
|
||||
* 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
|
||||
// too soon, if saving is requested before the write completes. Without
|
||||
// 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:
|
||||
* {"example.com": {"key": "value", "my_number": "123"}}
|
||||
*/
|
||||
collect: function (docShell, frameTree) {
|
||||
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:
|
||||
* {"example.com": {"key": "value", "my_number": "123"}}
|
||||
*/
|
||||
restore: function (aDocShell, aStorageData) {
|
||||
restore(aDocShell, aStorageData) {
|
||||
SessionStorageInternal.restore(aDocShell, aStorageData);
|
||||
},
|
||||
});
|
||||
|
@ -62,7 +62,7 @@ var SessionStorageInternal = {
|
|||
* session storage data as strings. For example:
|
||||
* {"example.com": {"key": "value", "my_number": "123"}}
|
||||
*/
|
||||
collect: function (docShell, frameTree) {
|
||||
collect(docShell, frameTree) {
|
||||
let data = {};
|
||||
let visitedOrigins = new Set();
|
||||
|
||||
|
@ -108,7 +108,7 @@ var SessionStorageInternal = {
|
|||
* keys and per-host session storage data as strings. For example:
|
||||
* {"example.com": {"key": "value", "my_number": "123"}}
|
||||
*/
|
||||
restore: function (aDocShell, aStorageData) {
|
||||
restore(aDocShell, aStorageData) {
|
||||
for (let origin of Object.keys(aStorageData)) {
|
||||
let data = aStorageData[origin];
|
||||
|
||||
|
@ -149,7 +149,7 @@ var SessionStorageInternal = {
|
|||
* @param aDocShell
|
||||
* A tab's docshell (containing the sessionStorage)
|
||||
*/
|
||||
_readEntry: function (aPrincipal, aDocShell) {
|
||||
_readEntry(aPrincipal, aDocShell) {
|
||||
let hostData = {};
|
||||
let storage;
|
||||
|
||||
|
|
|
@ -326,7 +326,7 @@ this.SessionStore = {
|
|||
SessionStoreInternal.restoreLastSession();
|
||||
},
|
||||
|
||||
getCurrentState: function (aUpdateAll) {
|
||||
getCurrentState(aUpdateAll) {
|
||||
return SessionStoreInternal.getCurrentState(aUpdateAll);
|
||||
},
|
||||
|
||||
|
@ -383,7 +383,7 @@ this.SessionStore = {
|
|||
* The browser state for which we remove worth-saving tabs.
|
||||
* The given object will be modified.
|
||||
*/
|
||||
keepOnlyWorthSavingTabs: function (aState) {
|
||||
keepOnlyWorthSavingTabs(aState) {
|
||||
for (let i = aState.windows.length - 1; i >= 0; i--) {
|
||||
let win = aState.windows[i];
|
||||
for (let j = win.tabs.length - 1; j >= 0; j--) {
|
||||
|
@ -502,7 +502,7 @@ var SessionStoreInternal = {
|
|||
_closedObjectsChanged: false,
|
||||
|
||||
// A promise resolved once initialization is complete
|
||||
_deferredInitialized: (function () {
|
||||
_deferredInitialized: (function() {
|
||||
let deferred = {};
|
||||
|
||||
deferred.promise = new Promise((resolve, reject) => {
|
||||
|
@ -571,7 +571,7 @@ var SessionStoreInternal = {
|
|||
/**
|
||||
* Initialize the sessionstore service.
|
||||
*/
|
||||
init: function () {
|
||||
init() {
|
||||
if (this._initialized) {
|
||||
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
|
||||
*/
|
||||
initSession: function () {
|
||||
initSession() {
|
||||
TelemetryStopwatch.start("FX_SESSION_RESTORE_STARTUP_INIT_SESSION_MS");
|
||||
let state;
|
||||
let ss = gSessionStartup;
|
||||
|
@ -614,8 +614,7 @@ var SessionStoreInternal = {
|
|||
if (remainingState.windows.length) {
|
||||
LastSession.setState(remainingState);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// Get the last deferred session in case the user still wants to
|
||||
// restore it
|
||||
LastSession.setState(state.lastSessionState);
|
||||
|
@ -655,8 +654,7 @@ var SessionStoreInternal = {
|
|||
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
|
||||
|
@ -669,7 +667,7 @@ var SessionStoreInternal = {
|
|||
return state;
|
||||
},
|
||||
|
||||
_initPrefs : function() {
|
||||
_initPrefs() {
|
||||
this._prefBranch = Services.prefs.getBranch("browser.");
|
||||
|
||||
gDebuggingEnabled = this._prefBranch.getBoolPref("sessionstore.debug");
|
||||
|
@ -858,7 +856,7 @@ var SessionStoreInternal = {
|
|||
}
|
||||
}
|
||||
break;
|
||||
case "SessionStore:restoreHistoryComplete":
|
||||
case "SessionStore:restoreHistoryComplete": {
|
||||
// Notify the tabbrowser that the tab chrome has been restored.
|
||||
let tabData = TabState.collect(tab);
|
||||
|
||||
|
@ -902,6 +900,7 @@ var SessionStoreInternal = {
|
|||
event.initEvent("SSTabRestoring", true, false);
|
||||
tab.dispatchEvent(event);
|
||||
break;
|
||||
}
|
||||
case "SessionStore:restoreTabContentStarted":
|
||||
if (browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE) {
|
||||
// If a load not initiated by sessionstore was started in a
|
||||
|
@ -947,7 +946,6 @@ var SessionStoreInternal = {
|
|||
break;
|
||||
default:
|
||||
throw new Error(`received unknown message '${aMessage.name}'`);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -957,8 +955,8 @@ var SessionStoreInternal = {
|
|||
* {histogramID: value, ...} An object mapping histogramIDs to the
|
||||
* value to be recorded for that ID,
|
||||
*/
|
||||
recordTelemetry: function (telemetry) {
|
||||
for (let histogramId in telemetry){
|
||||
recordTelemetry(telemetry) {
|
||||
for (let histogramId in telemetry) {
|
||||
Telemetry.getHistogramById(histogramId).add(telemetry[histogramId]);
|
||||
}
|
||||
},
|
||||
|
@ -1139,22 +1137,19 @@ var SessionStoreInternal = {
|
|||
let options = {firstWindow: true, overwriteTabs: overwrite};
|
||||
this.restoreWindows(aWindow, aInitialState, options);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// Nothing to restore, notify observers things are complete.
|
||||
Services.obs.notifyObservers(null, NOTIFY_WINDOWS_RESTORED, "");
|
||||
}
|
||||
}
|
||||
// this window was opened by _openWindowWithState
|
||||
else if (!this._isWindowLoaded(aWindow)) {
|
||||
} else if (!this._isWindowLoaded(aWindow)) {
|
||||
let state = this._statesToRestore[aWindow.__SS_restoreID];
|
||||
let options = {overwriteTabs: true, isFollowUp: state.windows.length == 1};
|
||||
this.restoreWindow(aWindow, state.windows[0], options);
|
||||
}
|
||||
// The user opened another, non-private window after starting up with
|
||||
// a single private one. Let's restore the session we actually wanted to
|
||||
// restore at startup.
|
||||
else if (this._deferredInitialState && !isPrivateWindow &&
|
||||
} else if (this._deferredInitialState && !isPrivateWindow &&
|
||||
aWindow.toolbar.visible) {
|
||||
|
||||
// global data must be restored before restoreWindow is called so that
|
||||
|
@ -1165,8 +1160,7 @@ var SessionStoreInternal = {
|
|||
this._deferredInitialState.windows.length : 0;
|
||||
this.restoreWindows(aWindow, this._deferredInitialState, {firstWindow: true});
|
||||
this._deferredInitialState = null;
|
||||
}
|
||||
else if (this._restoreLastWindow && aWindow.toolbar.visible &&
|
||||
} else if (this._restoreLastWindow && aWindow.toolbar.visible &&
|
||||
this._closedWindows.length && !isPrivateWindow) {
|
||||
|
||||
// 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
|
||||
if (!normalTabsState.windows.length) {
|
||||
this._removeClosedWindow(closedWindowIndex);
|
||||
}
|
||||
// Or update _closedWindows with the modified state
|
||||
else {
|
||||
} else {
|
||||
delete normalTabsState.windows[0].__lastSessionWindowID;
|
||||
this._closedWindows[closedWindowIndex] = normalTabsState.windows[0];
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// If we're just restoring the window, make sure it gets removed from
|
||||
// _closedWindows.
|
||||
this._removeClosedWindow(closedWindowIndex);
|
||||
|
@ -1241,7 +1233,7 @@ var SessionStoreInternal = {
|
|||
* @param aWindow
|
||||
* Window reference
|
||||
*/
|
||||
onBeforeBrowserWindowShown: function (aWindow) {
|
||||
onBeforeBrowserWindowShown(aWindow) {
|
||||
// Register the window.
|
||||
this.onLoad(aWindow);
|
||||
|
||||
|
@ -1547,7 +1539,7 @@ var SessionStoreInternal = {
|
|||
/**
|
||||
* 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
|
||||
this._forEachBrowserWindow((win) => {
|
||||
this._collectWindowData(win);
|
||||
|
@ -1623,7 +1615,7 @@ var SessionStoreInternal = {
|
|||
*
|
||||
* @return Promise
|
||||
*/
|
||||
flushAllWindowsAsync: Task.async(function*(progress={}) {
|
||||
flushAllWindowsAsync: Task.async(function*(progress = {}) {
|
||||
let windowPromises = new Map();
|
||||
// We collect flush promises and close each window immediately so that
|
||||
// the user can't start changing any window state while we're waiting
|
||||
|
@ -1651,7 +1643,7 @@ var SessionStoreInternal = {
|
|||
yield promise;
|
||||
this._collectWindowData(win);
|
||||
progress.current++;
|
||||
};
|
||||
}
|
||||
|
||||
// We must cache this because _getMostRecentBrowserWindow will always
|
||||
// return null by the time quit-application occurs.
|
||||
|
@ -1782,8 +1774,7 @@ var SessionStoreInternal = {
|
|||
}
|
||||
if (openTabs.length == 0) {
|
||||
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
|
||||
let selectedTab = openTabs[this._closedWindows[ix].selected - 1];
|
||||
// some duplication from restoreHistory - make sure we get the correct title
|
||||
|
@ -2078,7 +2069,7 @@ var SessionStoreInternal = {
|
|||
* @param aBrowser
|
||||
* The <xul:browser> that is now in the crashed state.
|
||||
*/
|
||||
onBrowserCrashed: function(aBrowser) {
|
||||
onBrowserCrashed(aBrowser) {
|
||||
NS_ASSERT(aBrowser.isRemoteBrowser,
|
||||
"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.
|
||||
// Do not reschedule a save. This will wait for the next regular
|
||||
// save.
|
||||
onIdleDaily: function() {
|
||||
onIdleDaily() {
|
||||
// Remove old closed windows
|
||||
this._cleanupOldData([this._closedWindows]);
|
||||
|
||||
|
@ -2128,12 +2119,12 @@ var SessionStoreInternal = {
|
|||
},
|
||||
|
||||
// Remove "old" data from an array
|
||||
_cleanupOldData: function(targets) {
|
||||
_cleanupOldData(targets) {
|
||||
const TIME_TO_LIVE = this._prefBranch.getIntPref("sessionstore.cleanup.forget_closed_after");
|
||||
const now = Date.now();
|
||||
|
||||
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];
|
||||
// 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
|
||||
|
@ -2166,8 +2157,7 @@ var SessionStoreInternal = {
|
|||
|
||||
try {
|
||||
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) {
|
||||
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) {
|
||||
if ("__SSi" in aWindow) {
|
||||
var data = this._windows[aWindow.__SSi].extData || {};
|
||||
let data = this._windows[aWindow.__SSi].extData || {};
|
||||
return data[aKey] || "";
|
||||
}
|
||||
|
||||
|
@ -2658,12 +2648,11 @@ var SessionStoreInternal = {
|
|||
|
||||
// Restore into that window - pretend it's a followup since we'll already
|
||||
// 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.
|
||||
let options = {overwriteTabs: canOverwriteTabs, isFollowUp: true};
|
||||
this.restoreWindow(windowToUse, winState, options);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this._openWindowWithState({ windows: [winState] });
|
||||
}
|
||||
}
|
||||
|
@ -2794,10 +2783,10 @@ var SessionStoreInternal = {
|
|||
return;
|
||||
}
|
||||
|
||||
let window = tab.ownerGlobal;
|
||||
let refreshedWindow = tab.ownerGlobal;
|
||||
|
||||
// The tab or its window might be gone.
|
||||
if (!window || !window.__SSi || window.closed) {
|
||||
if (!refreshedWindow || !refreshedWindow.__SSi || refreshedWindow.closed) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2858,6 +2847,7 @@ var SessionStoreInternal = {
|
|||
let tabState = TabState.collect(tab);
|
||||
return { index: tabState.index - 1, entries: tabState.entries }
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -2886,7 +2876,6 @@ var SessionStoreInternal = {
|
|||
let homePages = ["about:blank"];
|
||||
let removableTabs = [];
|
||||
let tabbrowser = aWindow.gBrowser;
|
||||
let normalTabsLen = tabbrowser.tabs.length - tabbrowser._numPinnedTabs;
|
||||
let startupPref = this._prefBranch.getIntPref("startup.page");
|
||||
if (startupPref == 1)
|
||||
homePages = homePages.concat(aWindow.gHomeButton.getHomePage().split("|"));
|
||||
|
@ -2900,8 +2889,7 @@ var SessionStoreInternal = {
|
|||
|
||||
if (tabbrowser.tabs.length == removableTabs.length) {
|
||||
canOverwriteTabs = true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// If we're not overwriting all of the tabs, then close the home tabs.
|
||||
for (let i = removableTabs.length - 1; i >= 0; i--) {
|
||||
tabbrowser.removeTab(removableTabs.pop(), { animate: false });
|
||||
|
@ -2946,7 +2934,7 @@ var SessionStoreInternal = {
|
|||
* Bool update all windows
|
||||
* @returns object
|
||||
*/
|
||||
getCurrentState: function (aUpdateAll) {
|
||||
getCurrentState(aUpdateAll) {
|
||||
this._handleClosedWindows().then(() => {
|
||||
this._notifyOfClosedObjectsChange();
|
||||
});
|
||||
|
@ -2961,8 +2949,7 @@ var SessionStoreInternal = {
|
|||
return;
|
||||
if (aUpdateAll || DirtyWindows.has(aWindow) || aWindow == activeWindow) {
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
@ -3008,7 +2995,7 @@ var SessionStoreInternal = {
|
|||
// 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"
|
||||
// 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
|
||||
if (nonPopupCount == 0 && lastClosedWindowsCopy.length > 0 &&
|
||||
RunState.isQuitting) {
|
||||
|
@ -3040,7 +3027,7 @@ var SessionStoreInternal = {
|
|||
windows: total,
|
||||
selectedWindow: ix + 1,
|
||||
_closedWindows: lastClosedWindowsCopy,
|
||||
session: session,
|
||||
session,
|
||||
global: this._globalState.getState()
|
||||
};
|
||||
|
||||
|
@ -3084,7 +3071,7 @@ var SessionStoreInternal = {
|
|||
let windows = [this._windows[aWindow.__SSi]];
|
||||
SessionCookies.update(windows);
|
||||
|
||||
return { windows: windows };
|
||||
return { windows };
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -3163,11 +3150,9 @@ var SessionStoreInternal = {
|
|||
|
||||
if (!winData.tabs) {
|
||||
winData.tabs = [];
|
||||
}
|
||||
|
||||
// don't restore a single blank tab when we've had an external
|
||||
// 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 = [];
|
||||
}
|
||||
|
@ -3233,8 +3218,7 @@ var SessionStoreInternal = {
|
|||
|
||||
if (winData.tabs[t].hidden) {
|
||||
tabbrowser.hideTab(tabs[t]);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
tabbrowser.showTab(tabs[t]);
|
||||
numVisibleTabs++;
|
||||
}
|
||||
|
@ -3366,8 +3350,7 @@ var SessionStoreInternal = {
|
|||
let root;
|
||||
try {
|
||||
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);
|
||||
this._sendRestoreCompletedNotifications();
|
||||
return;
|
||||
|
@ -3589,7 +3572,7 @@ var SessionStoreInternal = {
|
|||
});
|
||||
|
||||
browser.messageManager.sendAsyncMessage("SessionStore:restoreHistory",
|
||||
{tabData: tabData, epoch: epoch, loadArguments});
|
||||
{tabData, epoch, loadArguments});
|
||||
|
||||
// Restore tab attributes.
|
||||
if ("attributes" in tabData) {
|
||||
|
@ -3618,7 +3601,7 @@ var SessionStoreInternal = {
|
|||
* @param aReloadInFreshProcess
|
||||
* 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) {
|
||||
return;
|
||||
}
|
||||
|
@ -3651,7 +3634,7 @@ var SessionStoreInternal = {
|
|||
let isRemotenessUpdate =
|
||||
tabbrowser.updateBrowserRemotenessByURL(browser, uri, {
|
||||
freshProcess: aReloadInFreshProcess,
|
||||
newFrameloader: newFrameloader,
|
||||
newFrameloader,
|
||||
});
|
||||
|
||||
if (isRemotenessUpdate) {
|
||||
|
@ -3663,8 +3646,8 @@ var SessionStoreInternal = {
|
|||
let epoch = this.startNextEpoch(browser);
|
||||
|
||||
browser.messageManager.sendAsyncMessage("SessionStore:restoreHistory", {
|
||||
tabData: tabData,
|
||||
epoch: epoch,
|
||||
tabData,
|
||||
epoch,
|
||||
loadArguments: aLoadArguments,
|
||||
isRemotenessUpdate,
|
||||
});
|
||||
|
@ -3736,7 +3719,7 @@ var SessionStoreInternal = {
|
|||
* Object containing session data for the window
|
||||
*/
|
||||
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) {
|
||||
aWindow[aItem].visible = hidden.indexOf(aItem) == -1;
|
||||
});
|
||||
|
@ -3747,8 +3730,7 @@ var SessionStoreInternal = {
|
|||
aWindow.gURLBar.readOnly = true;
|
||||
aWindow.gURLBar.setAttribute("enablehistory", "false");
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
delete this._windows[aWindow.__SSi].isPopup;
|
||||
if (aWindow.gURLBar) {
|
||||
aWindow.gURLBar.readOnly = false;
|
||||
|
@ -3756,14 +3738,13 @@ var SessionStoreInternal = {
|
|||
}
|
||||
}
|
||||
|
||||
var _this = this;
|
||||
aWindow.setTimeout(function() {
|
||||
_this.restoreDimensions.apply(_this, [aWindow,
|
||||
aWindow.setTimeout(() => {
|
||||
this.restoreDimensions(aWindow,
|
||||
+(aWinData.width || 0),
|
||||
+(aWinData.height || 0),
|
||||
"screenX" in aWinData ? +aWinData.screenX : NaN,
|
||||
"screenY" in aWinData ? +aWinData.screenY : NaN,
|
||||
aWinData.sizemode || "", aWinData.sidebar || ""]);
|
||||
aWinData.sizemode || "", aWinData.sidebar || "");
|
||||
}, 0);
|
||||
},
|
||||
|
||||
|
@ -3845,10 +3826,8 @@ var SessionStoreInternal = {
|
|||
aWindow.resizeTo(aWidth, aHeight);
|
||||
}
|
||||
}
|
||||
if (aSizeMode && win_("sizemode") != aSizeMode)
|
||||
{
|
||||
switch (aSizeMode)
|
||||
{
|
||||
if (aSizeMode && win_("sizemode") != aSizeMode) {
|
||||
switch (aSizeMode) {
|
||||
case "maximized":
|
||||
aWindow.maximize();
|
||||
break;
|
||||
|
@ -3880,7 +3859,7 @@ var SessionStoreInternal = {
|
|||
* Will mark the given window as dirty so that we will recollect its
|
||||
* data before we start writing.
|
||||
*/
|
||||
saveStateDelayed: function (aWindow = null) {
|
||||
saveStateDelayed(aWindow = null) {
|
||||
if (aWindow) {
|
||||
DirtyWindows.add(aWindow);
|
||||
}
|
||||
|
@ -4172,7 +4151,7 @@ var SessionStoreInternal = {
|
|||
* @param aURL is the single URL we're looking for
|
||||
* @returns whether the window data contains only the single URL passed
|
||||
*/
|
||||
_hasSingleTabWithURL: function(aWinData, aURL) {
|
||||
_hasSingleTabWithURL(aWinData, aURL) {
|
||||
if (aWinData &&
|
||||
aWinData.length == 1 &&
|
||||
aWinData[0].tabs &&
|
||||
|
@ -4539,7 +4518,7 @@ var SessionStoreInternal = {
|
|||
* @param aTab
|
||||
* The tab that will be "reset"
|
||||
*/
|
||||
_resetLocalTabRestoringState: function (aTab) {
|
||||
_resetLocalTabRestoringState(aTab) {
|
||||
NS_ASSERT(aTab.linkedBrowser.__SS_restoreState,
|
||||
"given tab is not restoring");
|
||||
|
||||
|
@ -4565,7 +4544,7 @@ var SessionStoreInternal = {
|
|||
}
|
||||
},
|
||||
|
||||
_resetTabRestoringState: function (tab) {
|
||||
_resetTabRestoringState(tab) {
|
||||
NS_ASSERT(tab.linkedBrowser.__SS_restoreState,
|
||||
"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
|
||||
* with respect to |browser|.
|
||||
*/
|
||||
isCurrentEpoch: function (browser, epoch) {
|
||||
isCurrentEpoch(browser, epoch) {
|
||||
return this.getCurrentEpoch(browser) == epoch;
|
||||
},
|
||||
|
||||
|
@ -4680,7 +4659,7 @@ var TabRestoreQueue = {
|
|||
get restoreOnDemand() {
|
||||
let updateValue = () => {
|
||||
let value = Services.prefs.getBoolPref(PREF);
|
||||
let definition = {value: value, configurable: true};
|
||||
let definition = {value, configurable: true};
|
||||
Object.defineProperty(this, "restoreOnDemand", definition);
|
||||
return value;
|
||||
}
|
||||
|
@ -4694,7 +4673,7 @@ var TabRestoreQueue = {
|
|||
get restorePinnedTabsOnDemand() {
|
||||
let updateValue = () => {
|
||||
let value = Services.prefs.getBoolPref(PREF);
|
||||
let definition = {value: value, configurable: true};
|
||||
let definition = {value, configurable: true};
|
||||
Object.defineProperty(this, "restorePinnedTabsOnDemand", definition);
|
||||
return value;
|
||||
}
|
||||
|
@ -4708,7 +4687,7 @@ var TabRestoreQueue = {
|
|||
get restoreHiddenTabs() {
|
||||
let updateValue = () => {
|
||||
let value = Services.prefs.getBoolPref(PREF);
|
||||
let definition = {value: value, configurable: true};
|
||||
let definition = {value, configurable: true};
|
||||
Object.defineProperty(this, "restoreHiddenTabs", definition);
|
||||
return value;
|
||||
}
|
||||
|
@ -4720,12 +4699,12 @@ var TabRestoreQueue = {
|
|||
},
|
||||
|
||||
// Resets the queue and removes all tabs.
|
||||
reset: function () {
|
||||
reset() {
|
||||
this.tabs = {priority: [], visible: [], hidden: []};
|
||||
},
|
||||
|
||||
// Adds a tab to the queue and determines its priority bucket.
|
||||
add: function (tab) {
|
||||
add(tab) {
|
||||
let {priority, hidden, visible} = this.tabs;
|
||||
|
||||
if (tab.pinned) {
|
||||
|
@ -4738,7 +4717,7 @@ var TabRestoreQueue = {
|
|||
},
|
||||
|
||||
// Removes a given tab from the queue, if it's in there.
|
||||
remove: function (tab) {
|
||||
remove(tab) {
|
||||
let {priority, hidden, visible} = this.tabs;
|
||||
|
||||
// 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.
|
||||
shift: function () {
|
||||
shift() {
|
||||
let set;
|
||||
let {priority, hidden, visible} = this.tabs;
|
||||
|
||||
|
@ -4777,7 +4756,7 @@ var TabRestoreQueue = {
|
|||
},
|
||||
|
||||
// Moves a given tab from the 'hidden' to the 'visible' bucket.
|
||||
hiddenToVisible: function (tab) {
|
||||
hiddenToVisible(tab) {
|
||||
let {hidden, visible} = this.tabs;
|
||||
let index = hidden.indexOf(tab);
|
||||
|
||||
|
@ -4788,7 +4767,7 @@ var TabRestoreQueue = {
|
|||
},
|
||||
|
||||
// Moves a given tab from the 'visible' to the 'hidden' bucket.
|
||||
visibleToHidden: function (tab) {
|
||||
visibleToHidden(tab) {
|
||||
let {visible, hidden} = this.tabs;
|
||||
let index = visible.indexOf(tab);
|
||||
|
||||
|
@ -4806,7 +4785,7 @@ var TabRestoreQueue = {
|
|||
* The tab to check
|
||||
* @returns bool
|
||||
*/
|
||||
willRestoreSoon: function (tab) {
|
||||
willRestoreSoon(tab) {
|
||||
let { priority, hidden, visible } = this.tabs;
|
||||
let { restoreOnDemand, restorePinnedTabsOnDemand,
|
||||
restoreHiddenTabs } = this.prefs;
|
||||
|
@ -4834,19 +4813,19 @@ var TabRestoreQueue = {
|
|||
var DyingWindowCache = {
|
||||
_data: new WeakMap(),
|
||||
|
||||
has: function (window) {
|
||||
has(window) {
|
||||
return this._data.has(window);
|
||||
},
|
||||
|
||||
get: function (window) {
|
||||
get(window) {
|
||||
return this._data.get(window);
|
||||
},
|
||||
|
||||
set: function (window, data) {
|
||||
set(window, data) {
|
||||
this._data.set(window, data);
|
||||
},
|
||||
|
||||
remove: function (window) {
|
||||
remove(window) {
|
||||
this._data.delete(window);
|
||||
}
|
||||
};
|
||||
|
@ -4856,19 +4835,19 @@ var DyingWindowCache = {
|
|||
var DirtyWindows = {
|
||||
_data: new WeakMap(),
|
||||
|
||||
has: function (window) {
|
||||
has(window) {
|
||||
return this._data.has(window);
|
||||
},
|
||||
|
||||
add: function (window) {
|
||||
add(window) {
|
||||
return this._data.set(window, true);
|
||||
},
|
||||
|
||||
remove: function (window) {
|
||||
remove(window) {
|
||||
this._data.delete(window);
|
||||
},
|
||||
|
||||
clear: function (window) {
|
||||
clear(window) {
|
||||
this._data = new WeakMap();
|
||||
}
|
||||
};
|
||||
|
@ -4884,15 +4863,15 @@ var LastSession = {
|
|||
return !!this._state;
|
||||
},
|
||||
|
||||
getState: function () {
|
||||
getState() {
|
||||
return this._state;
|
||||
},
|
||||
|
||||
setState: function (state) {
|
||||
setState(state) {
|
||||
this._state = state;
|
||||
},
|
||||
|
||||
clear: function () {
|
||||
clear() {
|
||||
if (this._state) {
|
||||
this._state = 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,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* eslint-env worker */
|
||||
|
||||
/**
|
||||
* 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
|
||||
* Paths.recovery
|
||||
*/
|
||||
write: function (state, options = {}) {
|
||||
write(state, options = {}) {
|
||||
let exn;
|
||||
let telemetry = {};
|
||||
|
||||
|
@ -227,7 +229,7 @@ var Agent = {
|
|||
|
||||
try {
|
||||
iterator = new File.DirectoryIterator(this.Paths.backups);
|
||||
iterator.forEach(function (file) {
|
||||
iterator.forEach(function(file) {
|
||||
if (file.path.startsWith(upgradeBackupPrefix)) {
|
||||
backups.push(file.path);
|
||||
}
|
||||
|
@ -276,14 +278,14 @@ var Agent = {
|
|||
result: {
|
||||
upgradeBackup: upgradeBackupComplete
|
||||
},
|
||||
telemetry: telemetry,
|
||||
telemetry,
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Wipes all files holding session data from disk.
|
||||
*/
|
||||
wipe: function () {
|
||||
wipe() {
|
||||
|
||||
// Don't stop immediately in case of error.
|
||||
let exn = null;
|
||||
|
@ -332,7 +334,7 @@ var Agent = {
|
|||
* @param {string|null} prefix If provided, only remove files whose
|
||||
* name starts with a specific prefix.
|
||||
*/
|
||||
_wipeFromDir: function(path, prefix) {
|
||||
_wipeFromDir(path, prefix) {
|
||||
// Sanity check
|
||||
if (typeof prefix == "undefined" || prefix == "") {
|
||||
throw new TypeError();
|
||||
|
|
|
@ -57,7 +57,7 @@ this.StartupPerformance = {
|
|||
_totalNumberOfTabs: 0,
|
||||
_totalNumberOfWindows: 0,
|
||||
|
||||
init: function() {
|
||||
init() {
|
||||
for (let topic of OBSERVED_TOPICS) {
|
||||
Services.obs.addObserver(this, topic, false);
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ this.StartupPerformance = {
|
|||
// Called when restoration starts.
|
||||
// Record the start timestamp, setup the timer and `this._promiseFinished`.
|
||||
// Behavior is unspecified if there was already an ongoing measure.
|
||||
_onRestorationStarts: function(isAutoRestore) {
|
||||
_onRestorationStarts(isAutoRestore) {
|
||||
this._latestRestoredTimeStamp = this._startTimeStamp = Date.now();
|
||||
this._totalNumberOfEagerTabs = 0;
|
||||
this._totalNumberOfTabs = 0;
|
||||
|
@ -131,7 +131,7 @@ this.StartupPerformance = {
|
|||
});
|
||||
},
|
||||
|
||||
_startTimer: function() {
|
||||
_startTimer() {
|
||||
if (this._hasFired) {
|
||||
return;
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ this.StartupPerformance = {
|
|||
}, COLLECT_RESULTS_AFTER_MS);
|
||||
},
|
||||
|
||||
observe: function(subject, topic, details) {
|
||||
observe(subject, topic, details) {
|
||||
try {
|
||||
switch (topic) {
|
||||
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
|
||||
// the given tab data is restored to a new tab.
|
||||
this.TabAttributes = Object.freeze({
|
||||
persist: function (name) {
|
||||
persist(name) {
|
||||
return TabAttributesInternal.persist(name);
|
||||
},
|
||||
|
||||
get: function (tab) {
|
||||
get(tab) {
|
||||
return TabAttributesInternal.get(tab);
|
||||
},
|
||||
|
||||
set: function (tab, data = {}) {
|
||||
set(tab, data = {}) {
|
||||
TabAttributesInternal.set(tab, data);
|
||||
}
|
||||
});
|
||||
|
@ -36,7 +36,7 @@ this.TabAttributes = Object.freeze({
|
|||
var TabAttributesInternal = {
|
||||
_attrs: new Set(),
|
||||
|
||||
persist: function (name) {
|
||||
persist(name) {
|
||||
if (this._attrs.has(name) || ATTRIBUTES_TO_SKIP.has(name)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ var TabAttributesInternal = {
|
|||
return true;
|
||||
},
|
||||
|
||||
get: function (tab) {
|
||||
get(tab) {
|
||||
let data = {};
|
||||
|
||||
for (let name of this._attrs) {
|
||||
|
@ -57,7 +57,7 @@ var TabAttributesInternal = {
|
|||
return data;
|
||||
},
|
||||
|
||||
set: function (tab, data = {}) {
|
||||
set(tab, data = {}) {
|
||||
// Clear attributes.
|
||||
for (let name of this._attrs) {
|
||||
tab.removeAttribute(name);
|
||||
|
|
|
@ -23,15 +23,15 @@ XPCOMUtils.defineLazyModuleGetter(this, "Utils",
|
|||
* Module that contains tab state collection methods.
|
||||
*/
|
||||
this.TabState = Object.freeze({
|
||||
update: function (browser, data) {
|
||||
update(browser, data) {
|
||||
TabStateInternal.update(browser, data);
|
||||
},
|
||||
|
||||
collect: function (tab) {
|
||||
collect(tab) {
|
||||
return TabStateInternal.collect(tab);
|
||||
},
|
||||
|
||||
clone: function (tab) {
|
||||
clone(tab) {
|
||||
return TabStateInternal.clone(tab);
|
||||
},
|
||||
|
||||
|
@ -44,7 +44,7 @@ var TabStateInternal = {
|
|||
/**
|
||||
* Processes a data update sent by the content script.
|
||||
*/
|
||||
update: function (browser, {data}) {
|
||||
update(browser, {data}) {
|
||||
TabStateCache.update(browser, data);
|
||||
},
|
||||
|
||||
|
@ -58,7 +58,7 @@ var TabStateInternal = {
|
|||
* tab has not been invalidated since the last call to
|
||||
* collect(aTab), the same object is returned.
|
||||
*/
|
||||
collect: function (tab) {
|
||||
collect(tab) {
|
||||
return this._collectBaseTabData(tab);
|
||||
},
|
||||
|
||||
|
@ -73,7 +73,7 @@ var TabStateInternal = {
|
|||
* cached, it will always be read from the tab and thus be
|
||||
* up-to-date.
|
||||
*/
|
||||
clone: function (tab) {
|
||||
clone(tab) {
|
||||
return this._collectBaseTabData(tab, {includePrivateData: true});
|
||||
},
|
||||
|
||||
|
@ -87,7 +87,7 @@ var TabStateInternal = {
|
|||
*
|
||||
* @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 browser = tab.linkedBrowser;
|
||||
|
||||
|
@ -164,7 +164,6 @@ var TabStateInternal = {
|
|||
|
||||
// The caller may explicitly request to omit privacy checks.
|
||||
let includePrivateData = options && options.includePrivateData;
|
||||
let isPinned = !!tabData.pinned;
|
||||
|
||||
for (let key of Object.keys(data)) {
|
||||
let value = data[key];
|
||||
|
|
|
@ -26,7 +26,7 @@ this.TabStateCache = Object.freeze({
|
|||
* The cached data stored for the given |tab|
|
||||
* or associated |browser|.
|
||||
*/
|
||||
get: function (browserOrTab) {
|
||||
get(browserOrTab) {
|
||||
return TabStateCacheInternal.get(browserOrTab);
|
||||
},
|
||||
|
||||
|
@ -39,7 +39,7 @@ this.TabStateCache = Object.freeze({
|
|||
* The new data to be stored for the given |tab|
|
||||
* or associated |browser|.
|
||||
*/
|
||||
update: function (browserOrTab, newData) {
|
||||
update(browserOrTab, newData) {
|
||||
TabStateCacheInternal.update(browserOrTab, newData);
|
||||
}
|
||||
});
|
||||
|
@ -56,7 +56,7 @@ var TabStateCacheInternal = {
|
|||
* The cached data stored for the given |tab|
|
||||
* or associated |browser|.
|
||||
*/
|
||||
get: function (browserOrTab) {
|
||||
get(browserOrTab) {
|
||||
return this._data.get(browserOrTab.permanentKey);
|
||||
},
|
||||
|
||||
|
@ -70,7 +70,7 @@ var TabStateCacheInternal = {
|
|||
* @param change (object)
|
||||
* The actual changed values per domain.
|
||||
*/
|
||||
updatePartialStorageChange: function (data, change) {
|
||||
updatePartialStorageChange(data, change) {
|
||||
if (!data.storage) {
|
||||
data.storage = {};
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ var TabStateCacheInternal = {
|
|||
* Object containing the tail of the history array, and
|
||||
* some additional metadata.
|
||||
*/
|
||||
updatePartialHistoryChange: function (data, change) {
|
||||
updatePartialHistoryChange(data, change) {
|
||||
const kLastIndex = Number.MAX_SAFE_INTEGER - 1;
|
||||
|
||||
if (!data.history) {
|
||||
|
@ -140,7 +140,7 @@ var TabStateCacheInternal = {
|
|||
* The new data to be stored for the given |tab|
|
||||
* or associated |browser|.
|
||||
*/
|
||||
update: function (browserOrTab, newData) {
|
||||
update(browserOrTab, newData) {
|
||||
let data = this._data.get(browserOrTab.permanentKey) || {};
|
||||
|
||||
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
|
||||
* event that a flush failed.
|
||||
*/
|
||||
resolve(browser, flushID, success=true, message="") {
|
||||
resolve(browser, flushID, success = true, 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
|
||||
* event that the flushes failed.
|
||||
*/
|
||||
resolveAll(browser, success=true, message="") {
|
||||
resolveAll(browser, success = true, message = "") {
|
||||
TabStateFlusherInternal.resolveAll(browser, success, message);
|
||||
}
|
||||
});
|
||||
|
@ -124,7 +124,7 @@ var TabStateFlusherInternal = {
|
|||
* An error message that will be sent to the Console in the
|
||||
* 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.
|
||||
if (!this._requests.has(browser.permanentKey)) {
|
||||
return;
|
||||
|
@ -160,7 +160,7 @@ var TabStateFlusherInternal = {
|
|||
* An error message that will be sent to the Console in the
|
||||
* 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.
|
||||
if (!this._requests.has(browser.permanentKey)) {
|
||||
return;
|
||||
|
|
|
@ -194,15 +194,13 @@ function onListClick(aEvent) {
|
|||
!treeView.isContainer(cell.row)) {
|
||||
restoreSingleTab(cell.row, aEvent.shiftKey);
|
||||
aEvent.stopPropagation();
|
||||
}
|
||||
else if (cell.col.id == "restore")
|
||||
} else if (cell.col.id == "restore")
|
||||
toggleRowChecked(cell.row);
|
||||
}
|
||||
}
|
||||
|
||||
function onListKeyDown(aEvent) {
|
||||
switch (aEvent.keyCode)
|
||||
{
|
||||
switch (aEvent.keyCode) {
|
||||
case KeyEvent.DOM_VK_SPACE:
|
||||
toggleRowChecked(document.getElementById("tabList").currentIndex);
|
||||
// Prevent page from scrolling on the space key.
|
||||
|
@ -239,11 +237,16 @@ function toggleRowChecked(aIx) {
|
|||
tab.checked = item.checked;
|
||||
treeView.treeBox.invalidateRow(gTreeData.indexOf(tab));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// update the window's checkmark as well (0 means "partially checked")
|
||||
item.parent.checked = item.parent.tabs.every(isChecked) ? true :
|
||||
item.parent.tabs.some(isChecked) ? 0 : false;
|
||||
} else {
|
||||
// Update the window's checkmark as well (0 means "partially checked").
|
||||
let state = false;
|
||||
if (item.parent.tabs.every(isChecked)) {
|
||||
state = true;
|
||||
} else if (item.parent.tabs.some(isChecked)) {
|
||||
state = 0;
|
||||
}
|
||||
item.parent.checked = state;
|
||||
|
||||
treeView.treeBox.invalidateRow(gTreeData.indexOf(item.parent));
|
||||
}
|
||||
|
||||
|
@ -277,20 +280,20 @@ var treeView = {
|
|||
treeBox: null,
|
||||
selection: null,
|
||||
|
||||
get rowCount() { return gTreeData.length; },
|
||||
setTree: function(treeBox) { this.treeBox = treeBox; },
|
||||
getCellText: function(idx, column) { return gTreeData[idx].label; },
|
||||
isContainer: function(idx) { return "open" in gTreeData[idx]; },
|
||||
getCellValue: function(idx, column){ return gTreeData[idx].checked; },
|
||||
isContainerOpen: function(idx) { return gTreeData[idx].open; },
|
||||
isContainerEmpty: function(idx) { return false; },
|
||||
isSeparator: function(idx) { return false; },
|
||||
isSorted: function() { return false; },
|
||||
isEditable: function(idx, column) { return false; },
|
||||
canDrop: function(idx, orientation, dt) { return false; },
|
||||
getLevel: function(idx) { return this.isContainer(idx) ? 0 : 1; },
|
||||
get rowCount() { return gTreeData.length; },
|
||||
setTree(treeBox) { this.treeBox = treeBox; },
|
||||
getCellText(idx, column) { return gTreeData[idx].label; },
|
||||
isContainer(idx) { return "open" in gTreeData[idx]; },
|
||||
getCellValue(idx, column) { return gTreeData[idx].checked; },
|
||||
isContainerOpen(idx) { return gTreeData[idx].open; },
|
||||
isContainerEmpty(idx) { return false; },
|
||||
isSeparator(idx) { return false; },
|
||||
isSorted() { return false; },
|
||||
isEditable(idx, column) { return false; },
|
||||
canDrop(idx, orientation, dt) { return false; },
|
||||
getLevel(idx) { return this.isContainer(idx) ? 0 : 1; },
|
||||
|
||||
getParentIndex: function(idx) {
|
||||
getParentIndex(idx) {
|
||||
if (!this.isContainer(idx))
|
||||
for (var t = idx - 1; t >= 0 ; t--)
|
||||
if (this.isContainer(t))
|
||||
|
@ -298,7 +301,7 @@ var treeView = {
|
|||
return -1;
|
||||
},
|
||||
|
||||
hasNextSibling: function(idx, after) {
|
||||
hasNextSibling(idx, after) {
|
||||
var thisLevel = this.getLevel(idx);
|
||||
for (var t = after + 1; t < gTreeData.length; t++)
|
||||
if (this.getLevel(t) <= thisLevel)
|
||||
|
@ -306,7 +309,7 @@ var treeView = {
|
|||
return false;
|
||||
},
|
||||
|
||||
toggleOpenState: function(idx) {
|
||||
toggleOpenState(idx) {
|
||||
if (!this.isContainer(idx))
|
||||
return;
|
||||
var item = gTreeData[idx];
|
||||
|
@ -317,8 +320,7 @@ var treeView = {
|
|||
var deletecount = t - idx - 1;
|
||||
gTreeData.splice(idx + 1, deletecount);
|
||||
this.treeBox.rowCountChanged(idx + 1, -deletecount);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// add this window's tab rows to the view
|
||||
var toinsert = gTreeData[idx].tabs;
|
||||
for (var i = 0; i < toinsert.length; i++)
|
||||
|
@ -329,7 +331,7 @@ var treeView = {
|
|||
this.treeBox.invalidateRow(idx);
|
||||
},
|
||||
|
||||
getCellProperties: function(idx, column) {
|
||||
getCellProperties(idx, column) {
|
||||
if (column.id == "restore" && this.isContainer(idx) && gTreeData[idx].checked === 0)
|
||||
return "partial";
|
||||
if (column.id == "title")
|
||||
|
@ -338,7 +340,7 @@ var treeView = {
|
|||
return "";
|
||||
},
|
||||
|
||||
getRowProperties: function(idx) {
|
||||
getRowProperties(idx) {
|
||||
var winState = gTreeData[idx].parent || gTreeData[idx];
|
||||
if (winState.ix % 2 != 0)
|
||||
return "alternate";
|
||||
|
@ -346,17 +348,17 @@ var treeView = {
|
|||
return "";
|
||||
},
|
||||
|
||||
getImageSrc: function(idx, column) {
|
||||
getImageSrc(idx, column) {
|
||||
if (column.id == "title")
|
||||
return gTreeData[idx].src || null;
|
||||
return null;
|
||||
},
|
||||
|
||||
getProgressMode : function(idx, column) { },
|
||||
cycleHeader: function(column) { },
|
||||
cycleCell: function(idx, column) { },
|
||||
selectionChanged: function() { },
|
||||
performAction: function(action) { },
|
||||
performActionOnCell: function(action, index, column) { },
|
||||
getColumnProperties: function(column) { return ""; }
|
||||
getProgressMode(idx, column) { },
|
||||
cycleHeader(column) { },
|
||||
cycleCell(idx, column) { },
|
||||
selectionChanged() { },
|
||||
performAction(action) { },
|
||||
performActionOnCell(action, index, column) { },
|
||||
getColumnProperties(column) { return ""; }
|
||||
};
|
||||
|
|
|
@ -2,11 +2,9 @@
|
|||
* 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";
|
||||
/* eslint-env mozilla/frame-script */
|
||||
|
||||
function debug(msg) {
|
||||
Services.console.logStringMessage("SessionStoreContent: " + msg);
|
||||
}
|
||||
"use strict";
|
||||
|
||||
var Cu = Components.utils;
|
||||
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/Timer.jsm", this);
|
||||
Cu.import("resource://gre/modules/Services.jsm", this);
|
||||
|
||||
function debug(msg) {
|
||||
Services.console.logStringMessage("SessionStoreContent: " + msg);
|
||||
}
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "FormData",
|
||||
"resource://gre/modules/FormData.jsm");
|
||||
|
@ -36,7 +39,7 @@ Cu.import("resource:///modules/sessionstore/FrameTree.jsm", this);
|
|||
var gFrameTree = new FrameTree(this);
|
||||
|
||||
Cu.import("resource:///modules/sessionstore/ContentRestore.jsm", this);
|
||||
XPCOMUtils.defineLazyGetter(this, 'gContentRestore',
|
||||
XPCOMUtils.defineLazyGetter(this, "gContentRestore",
|
||||
() => { return new ContentRestore(this) });
|
||||
|
||||
// The current epoch.
|
||||
|
@ -76,11 +79,11 @@ function createLazy(fn) {
|
|||
*/
|
||||
var EventListener = {
|
||||
|
||||
init: function () {
|
||||
init() {
|
||||
addEventListener("load", this, true);
|
||||
},
|
||||
|
||||
handleEvent: function (event) {
|
||||
handleEvent(event) {
|
||||
// Ignore load events from subframes.
|
||||
if (event.target != content.document) {
|
||||
return;
|
||||
|
@ -117,11 +120,11 @@ var MessageListener = {
|
|||
"SessionStore:becomeActiveProcess",
|
||||
],
|
||||
|
||||
init: function () {
|
||||
init() {
|
||||
this.MESSAGES.forEach(m => addMessageListener(m, this));
|
||||
},
|
||||
|
||||
receiveMessage: function ({name, data}) {
|
||||
receiveMessage({name, data}) {
|
||||
// The docShell might be gone. Don't process messages,
|
||||
// that will just lead to errors anyway.
|
||||
if (!docShell) {
|
||||
|
@ -230,7 +233,7 @@ var MessageListener = {
|
|||
* {entries: [{url: "about:mozilla", ...}, ...], index: 1}
|
||||
*/
|
||||
var SessionHistoryListener = {
|
||||
init: function () {
|
||||
init() {
|
||||
// The frame tree observer is needed to handle initial subframe loads.
|
||||
// It will redundantly invalidate with the SHistoryListener in some cases
|
||||
// but these invalidations are very cheap.
|
||||
|
@ -260,14 +263,14 @@ var SessionHistoryListener = {
|
|||
addEventListener("DOMTitleChanged", this);
|
||||
},
|
||||
|
||||
uninit: function () {
|
||||
uninit() {
|
||||
let sessionHistory = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
|
||||
if (sessionHistory) {
|
||||
sessionHistory.removeSHistoryListener(this);
|
||||
}
|
||||
},
|
||||
|
||||
collect: function () {
|
||||
collect() {
|
||||
// We want to send down a historychange even for full collects in case our
|
||||
// session history is a partial session history, in which case we don't have
|
||||
// enough information for a full update. collectFrom(-1) tells the collect
|
||||
|
@ -286,7 +289,7 @@ var SessionHistoryListener = {
|
|||
// and send the entire history. We always send the additional info like the current selected
|
||||
// index (so for going back and forth between history entries we set the index to kLastIndex
|
||||
// if nothing else changed send an empty array and the additonal info like the selected index)
|
||||
collectFrom: function (idx) {
|
||||
collectFrom(idx) {
|
||||
if (this._fromIdx <= idx) {
|
||||
// If we already know that we need to update history fromn index N we can ignore any changes
|
||||
// tha happened with an element with index larger than N.
|
||||
|
@ -312,44 +315,44 @@ var SessionHistoryListener = {
|
|||
this.collect();
|
||||
},
|
||||
|
||||
onFrameTreeCollected: function () {
|
||||
onFrameTreeCollected() {
|
||||
this.collect();
|
||||
},
|
||||
|
||||
onFrameTreeReset: function () {
|
||||
onFrameTreeReset() {
|
||||
this.collect();
|
||||
},
|
||||
|
||||
OnHistoryNewEntry: function (newURI, oldIndex) {
|
||||
OnHistoryNewEntry(newURI, oldIndex) {
|
||||
this.collectFrom(oldIndex);
|
||||
},
|
||||
|
||||
OnHistoryGoBack: function (backURI) {
|
||||
OnHistoryGoBack(backURI) {
|
||||
this.collectFrom(kLastIndex);
|
||||
return true;
|
||||
},
|
||||
|
||||
OnHistoryGoForward: function (forwardURI) {
|
||||
OnHistoryGoForward(forwardURI) {
|
||||
this.collectFrom(kLastIndex);
|
||||
return true;
|
||||
},
|
||||
|
||||
OnHistoryGotoIndex: function (index, gotoURI) {
|
||||
OnHistoryGotoIndex(index, gotoURI) {
|
||||
this.collectFrom(kLastIndex);
|
||||
return true;
|
||||
},
|
||||
|
||||
OnHistoryPurge: function (numEntries) {
|
||||
OnHistoryPurge(numEntries) {
|
||||
this.collect();
|
||||
return true;
|
||||
},
|
||||
|
||||
OnHistoryReload: function (reloadURI, reloadFlags) {
|
||||
OnHistoryReload(reloadURI, reloadFlags) {
|
||||
this.collect();
|
||||
return true;
|
||||
},
|
||||
|
||||
OnHistoryReplaceEntry: function (index) {
|
||||
OnHistoryReplaceEntry(index) {
|
||||
this.collect();
|
||||
},
|
||||
|
||||
|
@ -372,12 +375,12 @@ var SessionHistoryListener = {
|
|||
* {scroll: "100,100", children: [null, null, {scroll: "200,200"}]}
|
||||
*/
|
||||
var ScrollPositionListener = {
|
||||
init: function () {
|
||||
init() {
|
||||
addEventListener("scroll", this);
|
||||
gFrameTree.addObserver(this);
|
||||
},
|
||||
|
||||
handleEvent: function (event) {
|
||||
handleEvent(event) {
|
||||
let frame = event.target.defaultView;
|
||||
|
||||
// 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());
|
||||
},
|
||||
|
||||
onFrameTreeReset: function () {
|
||||
onFrameTreeReset() {
|
||||
MessageQueue.push("scroll", () => null);
|
||||
},
|
||||
|
||||
collect: function () {
|
||||
collect() {
|
||||
return gFrameTree.map(ScrollPosition.collect);
|
||||
}
|
||||
};
|
||||
|
@ -418,13 +421,13 @@ var ScrollPositionListener = {
|
|||
* }
|
||||
*/
|
||||
var FormDataListener = {
|
||||
init: function () {
|
||||
init() {
|
||||
addEventListener("input", this, true);
|
||||
addEventListener("change", this, true);
|
||||
gFrameTree.addObserver(this);
|
||||
},
|
||||
|
||||
handleEvent: function (event) {
|
||||
handleEvent(event) {
|
||||
let frame = event.target.ownerGlobal;
|
||||
|
||||
// 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);
|
||||
},
|
||||
|
||||
collect: function () {
|
||||
collect() {
|
||||
return gFrameTree.map(FormData.collect);
|
||||
}
|
||||
};
|
||||
|
@ -455,18 +458,18 @@ var FormDataListener = {
|
|||
* {pageStyle: "Dusk", children: [null, {pageStyle: "Mozilla"}]}
|
||||
*/
|
||||
var PageStyleListener = {
|
||||
init: function () {
|
||||
init() {
|
||||
Services.obs.addObserver(this, "author-style-disabled-changed", false);
|
||||
Services.obs.addObserver(this, "style-sheet-applicable-state-changed", false);
|
||||
gFrameTree.addObserver(this);
|
||||
},
|
||||
|
||||
uninit: function () {
|
||||
uninit() {
|
||||
Services.obs.removeObserver(this, "author-style-disabled-changed");
|
||||
Services.obs.removeObserver(this, "style-sheet-applicable-state-changed");
|
||||
},
|
||||
|
||||
observe: function (subject, topic) {
|
||||
observe(subject, topic) {
|
||||
let frame = subject.defaultView;
|
||||
|
||||
if (frame && gFrameTree.contains(frame)) {
|
||||
|
@ -474,15 +477,15 @@ var PageStyleListener = {
|
|||
}
|
||||
},
|
||||
|
||||
collect: function () {
|
||||
collect() {
|
||||
return PageStyle.collect(docShell, gFrameTree);
|
||||
},
|
||||
|
||||
onFrameTreeCollected: function () {
|
||||
onFrameTreeCollected() {
|
||||
MessageQueue.push("pageStyle", () => this.collect());
|
||||
},
|
||||
|
||||
onFrameTreeReset: function () {
|
||||
onFrameTreeReset() {
|
||||
MessageQueue.push("pageStyle", () => null);
|
||||
}
|
||||
};
|
||||
|
@ -503,14 +506,14 @@ var DocShellCapabilitiesListener = {
|
|||
*/
|
||||
_latestCapabilities: "",
|
||||
|
||||
init: function () {
|
||||
init() {
|
||||
gFrameTree.addObserver(this);
|
||||
},
|
||||
|
||||
/**
|
||||
* 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
|
||||
// so calling join() without sorting before is totally sufficient.
|
||||
let caps = DocShellCapabilities.collect(docShell).join(",");
|
||||
|
@ -533,23 +536,23 @@ var DocShellCapabilitiesListener = {
|
|||
* as keys and per-host DOMSessionStorage data as values.
|
||||
*/
|
||||
var SessionStorageListener = {
|
||||
init: function () {
|
||||
init() {
|
||||
addEventListener("MozSessionStorageChanged", this, true);
|
||||
Services.obs.addObserver(this, "browser:purge-domain-data", false);
|
||||
gFrameTree.addObserver(this);
|
||||
},
|
||||
|
||||
uninit: function () {
|
||||
uninit() {
|
||||
Services.obs.removeObserver(this, "browser:purge-domain-data");
|
||||
},
|
||||
|
||||
handleEvent: function (event) {
|
||||
handleEvent(event) {
|
||||
if (gFrameTree.contains(event.target)) {
|
||||
this.collectFromEvent(event);
|
||||
}
|
||||
},
|
||||
|
||||
observe: function () {
|
||||
observe() {
|
||||
// Collect data on the next tick so that any other observer
|
||||
// that needs to purge data can do its work first.
|
||||
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-
|
||||
// efficient approximation: we compute the total sum of string lengths
|
||||
// involved in this object.
|
||||
estimateStorageSize: function(collected) {
|
||||
estimateStorageSize(collected) {
|
||||
if (!collected) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -593,11 +596,11 @@ var SessionStorageListener = {
|
|||
// reset these changes.
|
||||
_changes: undefined,
|
||||
|
||||
resetChanges: function () {
|
||||
resetChanges() {
|
||||
this._changes = undefined;
|
||||
},
|
||||
|
||||
collectFromEvent: function (event) {
|
||||
collectFromEvent(event) {
|
||||
// TODO: we should take browser.sessionstore.dom_storage_limit into an account here.
|
||||
if (docShell) {
|
||||
let {url, key, newValue} = event;
|
||||
|
@ -622,7 +625,7 @@ var SessionStorageListener = {
|
|||
}
|
||||
},
|
||||
|
||||
collect: function () {
|
||||
collect() {
|
||||
if (docShell) {
|
||||
// We need the entire session storage, let's reset the pending individual change
|
||||
// messages.
|
||||
|
@ -649,11 +652,11 @@ var SessionStorageListener = {
|
|||
}
|
||||
},
|
||||
|
||||
onFrameTreeCollected: function () {
|
||||
onFrameTreeCollected() {
|
||||
this.collect();
|
||||
},
|
||||
|
||||
onFrameTreeReset: function () {
|
||||
onFrameTreeReset() {
|
||||
this.collect();
|
||||
}
|
||||
};
|
||||
|
@ -669,7 +672,7 @@ var SessionStorageListener = {
|
|||
* not saved.
|
||||
*/
|
||||
var PrivacyListener = {
|
||||
init: function() {
|
||||
init() {
|
||||
docShell.addWeakPrivacyTransitionObserver(this);
|
||||
|
||||
// Check that value at startup as it might have
|
||||
|
@ -680,7 +683,7 @@ var PrivacyListener = {
|
|||
},
|
||||
|
||||
// Ci.nsIPrivacyTransitionObserver
|
||||
privateModeChanged: function(enabled) {
|
||||
privateModeChanged(enabled) {
|
||||
MessageQueue.push("isPrivate", () => enabled || null);
|
||||
},
|
||||
|
||||
|
@ -774,7 +777,7 @@ var MessageQueue = {
|
|||
* A function that returns the value that will be sent to the parent
|
||||
* process.
|
||||
*/
|
||||
push: function (key, fn) {
|
||||
push(key, fn) {
|
||||
this._data.set(key, createLazy(fn));
|
||||
|
||||
if (!this._timeout && !this._timeoutDisabled) {
|
||||
|
@ -790,7 +793,7 @@ var MessageQueue = {
|
|||
* {flushID: 123} to specify that this is a flush
|
||||
* {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
|
||||
// closed. The docShell is gone now and we can just return here as there
|
||||
// is nothing to do.
|
||||
|
@ -832,13 +835,14 @@ var MessageQueue = {
|
|||
isFinal: options.isFinal || false,
|
||||
epoch: gCurrentEpoch
|
||||
});
|
||||
} catch (ex if ex && ex.result == Cr.NS_ERROR_OUT_OF_MEMORY) {
|
||||
let telemetry = {
|
||||
FX_SESSION_RESTORE_SEND_UPDATE_CAUSED_OOM: 1
|
||||
};
|
||||
sendAsyncMessage("SessionStore:error", {
|
||||
telemetry
|
||||
});
|
||||
} catch (ex) {
|
||||
if (ex && ex.result == Cr.NS_ERROR_OUT_OF_MEMORY) {
|
||||
sendAsyncMessage("SessionStore:error", {
|
||||
telemetry: {
|
||||
FX_SESSION_RESTORE_SEND_UPDATE_CAUSED_OOM: 1
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -65,7 +65,7 @@ consoleMsg.init(aMsg, aException.fileName, null, aException.lineNumber, 0, Ci.ns
|
|||
Services.console.logMessage(consoleMsg);
|
||||
}
|
||||
|
||||
var gOnceInitializedDeferred = (function () {
|
||||
var gOnceInitializedDeferred = (function() {
|
||||
let deferred = {};
|
||||
|
||||
deferred.promise = new Promise((resolve, reject) => {
|
||||
|
@ -127,7 +127,7 @@ SessionStartup.prototype = {
|
|||
* @param source The Session State string read from disk.
|
||||
* @param parsed The object obtained by parsing |source| as JSON.
|
||||
*/
|
||||
_onSessionFileRead: function ({source, parsed, noFilesFound}) {
|
||||
_onSessionFileRead({source, parsed, noFilesFound}) {
|
||||
this._initialized = true;
|
||||
|
||||
// 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
|
||||
// assume there was no crash.
|
||||
this._previousSessionCrashed = !checkpoints["sessionstore-final-state-write-complete"];
|
||||
|
||||
} else {
|
||||
} else if (noFilesFound) {
|
||||
// If the Crash Monitor could not load a checkpoints file it will
|
||||
// provide null. This could occur on the first run after updating to
|
||||
// a version including the Crash Monitor, or if the checkpoints file
|
||||
// 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
|
||||
// so we will assume that this was a fresh profile.
|
||||
this._previousSessionCrashed = false;
|
||||
// There was no checkpoints file and no sessionstore.js or its backups
|
||||
// so we will assume that this was a fresh profile.
|
||||
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 {
|
||||
// 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);
|
||||
|
||||
|
||||
this._previousSessionCrashed = !stateFlagPresent ||
|
||||
(this._initialState.session.state == STATE_RUNNING_STR);
|
||||
}
|
||||
this._previousSessionCrashed = !stateFlagPresent ||
|
||||
(this._initialState.session.state == STATE_RUNNING_STR);
|
||||
}
|
||||
|
||||
// Report shutdown success via telemetry. Shortcoming here are
|
||||
|
@ -293,7 +288,7 @@ SessionStartup.prototype = {
|
|||
* crash, this method returns false.
|
||||
* @returns bool
|
||||
*/
|
||||
isAutomaticRestoreEnabled: function () {
|
||||
isAutomaticRestoreEnabled() {
|
||||
return Services.prefs.getBoolPref("browser.sessionstore.resume_session_once") ||
|
||||
Services.prefs.getIntPref("browser.startup.page") == BROWSER_STARTUP_RESUME_SESSION;
|
||||
},
|
||||
|
@ -302,7 +297,7 @@ SessionStartup.prototype = {
|
|||
* Determines whether there is a pending session restore.
|
||||
* @returns bool
|
||||
*/
|
||||
_willRestore: function () {
|
||||
_willRestore() {
|
||||
return this._sessionType == Ci.nsISessionStartup.RECOVER_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
|
||||
// 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);
|
||||
Object.defineProperty(SessionStoreService.prototype, aName, desc);
|
||||
});
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
"use strict";
|
||||
|
||||
const PREF = 'network.cookie.cookieBehavior';
|
||||
const PAGE_URL = 'http://mochi.test:8888/browser/' +
|
||||
'browser/components/sessionstore/test/browser_1234021_page.html';
|
||||
const PREF = "network.cookie.cookieBehavior";
|
||||
const PAGE_URL = "http://mochi.test:8888/browser/" +
|
||||
"browser/components/sessionstore/test/browser_1234021_page.html";
|
||||
const BEHAVIOR_REJECT = 2;
|
||||
|
||||
add_task(function* test() {
|
||||
yield pushPrefs([PREF, BEHAVIOR_REJECT]);
|
||||
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser: gBrowser,
|
||||
gBrowser,
|
||||
url: PAGE_URL
|
||||
}, function* handler(aBrowser) {
|
||||
yield TabStateFlusher.flush(aBrowser);
|
||||
|
|
|
@ -32,10 +32,10 @@ function test() {
|
|||
}
|
||||
});
|
||||
|
||||
function test(aLambda) {
|
||||
function checkNoThrow(aLambda) {
|
||||
try {
|
||||
return aLambda() || true;
|
||||
} catch(ex) { }
|
||||
} catch (ex) { }
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -73,9 +73,9 @@ function test() {
|
|||
(aValue.indexOf(aIx) > -1) == aOpt.selected);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Test (B) : Session data restoration between windows //
|
||||
//////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Test (B) : Session data restoration between windows
|
||||
*/
|
||||
|
||||
let rootDir = getRootDirectory(gTestPath);
|
||||
const testURL = rootDir + "browser_248970_b_sample.html";
|
||||
|
@ -93,7 +93,6 @@ function test() {
|
|||
"getClosedTabCount should return zero or at most max_tabs_undo");
|
||||
|
||||
// setup a state for tab (A) so we can check later that is restored
|
||||
let key = "key";
|
||||
let value = "Value " + Math.random();
|
||||
let state = { entries: [{ url: testURL }], extData: { key: value } };
|
||||
|
||||
|
@ -117,15 +116,15 @@ function test() {
|
|||
"getClosedTabCount has increased after closing a tab");
|
||||
|
||||
// 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");
|
||||
promiseTabRestored(tab_A_restored).then(() => {
|
||||
is(testURL, tab_A_restored.linkedBrowser.currentURI.spec,
|
||||
"it's the same tab that we expect");
|
||||
aWin.gBrowser.removeTab(tab_A_restored);
|
||||
|
||||
whenNewWindowLoaded({ private: true }, function(aWin) {
|
||||
windowsToClose.push(aWin);
|
||||
whenNewWindowLoaded({ private: true }, function(win) {
|
||||
windowsToClose.push(win);
|
||||
|
||||
// setup a state for tab (B) so we can check that its duplicated
|
||||
// properly
|
||||
|
@ -135,14 +134,14 @@ function test() {
|
|||
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(() => {
|
||||
// populate tab: (B) with different form data
|
||||
for (let item in fieldList)
|
||||
setFormValue(tab_B, item, fieldList[item]);
|
||||
|
||||
// duplicate tab: (B)
|
||||
let tab_C = aWin.gBrowser.duplicateTab(tab_B);
|
||||
let tab_C = win.gBrowser.duplicateTab(tab_B);
|
||||
promiseTabRestored(tab_C).then(() => {
|
||||
// verify the correctness of the duplicated tab
|
||||
is(ss.getTabValue(tab_C, key1), value1,
|
||||
|
@ -153,8 +152,8 @@ function test() {
|
|||
"The value for \"" + item + "\" was correctly duplicated");
|
||||
|
||||
// private browsing session, close tab: (C) and (B)
|
||||
aWin.gBrowser.removeTab(tab_C);
|
||||
aWin.gBrowser.removeTab(tab_B);
|
||||
win.gBrowser.removeTab(tab_C);
|
||||
win.gBrowser.removeTab(tab_B);
|
||||
|
||||
finish();
|
||||
});
|
||||
|
|
|
@ -5,40 +5,41 @@
|
|||
function test() {
|
||||
/** 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
|
||||
ok(test(() => ss.getWindowState({})),
|
||||
"Invalid window for getWindowState throws");
|
||||
ok(test(() => ss.setWindowState({}, "", false)),
|
||||
"Invalid window for setWindowState throws");
|
||||
ok(test(() => ss.getTabState({})),
|
||||
"Invalid tab for getTabState throws");
|
||||
ok(test(() => ss.setTabState({}, "{}")),
|
||||
"Invalid tab state for setTabState throws");
|
||||
ok(test(() => ss.setTabState({}, JSON.stringify({ entries: [] }))),
|
||||
"Invalid tab for setTabState throws");
|
||||
ok(test(() => ss.duplicateTab({}, {})),
|
||||
"Invalid tab for duplicateTab throws");
|
||||
ok(test(() => ss.duplicateTab({}, gBrowser.selectedTab)),
|
||||
"Invalid window for duplicateTab throws");
|
||||
ok(test(() => ss.getClosedTabData({})),
|
||||
"Invalid window for getClosedTabData throws");
|
||||
ok(test(() => ss.undoCloseTab({}, 0)),
|
||||
"Invalid window for undoCloseTab throws");
|
||||
ok(test(() => ss.undoCloseTab(window, -1)),
|
||||
"Invalid index for undoCloseTab throws");
|
||||
ok(test(() => ss.getWindowValue({}, "")),
|
||||
"Invalid window for getWindowValue throws");
|
||||
ok(test(() => ss.setWindowValue({}, "", "")),
|
||||
"Invalid window for setWindowValue throws");
|
||||
Assert.throws(() => ss.getWindowState({}),
|
||||
/NS_ERROR_ILLEGAL_VALUE/,
|
||||
"Invalid window for getWindowState throws");
|
||||
Assert.throws(() => ss.setWindowState({}, "", false),
|
||||
/NS_ERROR_ILLEGAL_VALUE/,
|
||||
"Invalid window for setWindowState throws");
|
||||
Assert.throws(() => ss.getTabState({}),
|
||||
/NS_ERROR_FAILURE/,
|
||||
"Invalid tab for getTabState throws");
|
||||
Assert.throws(() => ss.setTabState({}, "{}"),
|
||||
/NS_ERROR_FAILURE/,
|
||||
"Invalid tab state for setTabState throws");
|
||||
Assert.throws(() => ss.setTabState({}, JSON.stringify({ entries: [] })),
|
||||
/NS_ERROR_FAILURE/,
|
||||
"Invalid tab for setTabState throws");
|
||||
Assert.throws(() => ss.duplicateTab({}, {}),
|
||||
/NS_ERROR_FAILURE/,
|
||||
"Invalid tab for duplicateTab throws");
|
||||
Assert.throws(() => ss.duplicateTab({}, gBrowser.selectedTab),
|
||||
/NS_ERROR_ILLEGAL_VALUE/,
|
||||
"Invalid window for duplicateTab throws");
|
||||
Assert.throws(() => ss.getClosedTabData({}),
|
||||
/NS_ERROR_ILLEGAL_VALUE/,
|
||||
"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) {
|
||||
try {
|
||||
return aLambda() || true;
|
||||
}
|
||||
catch (ex) { }
|
||||
} catch (ex) { }
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
// setWindowValue, et al. //
|
||||
////////////////////////////
|
||||
/**
|
||||
* setWindowValue, et al.
|
||||
*/
|
||||
let key = "Unique name: " + Date.now();
|
||||
let value = "Unique value: " + Math.random();
|
||||
|
||||
|
@ -38,9 +37,9 @@ add_task(function* () {
|
|||
// test deleting a non-existent value
|
||||
ok(test(() => ss.deleteWindowValue(window, key)), "delete non-existent window value");
|
||||
|
||||
/////////////////////////
|
||||
// setTabValue, et al. //
|
||||
/////////////////////////
|
||||
/**
|
||||
* setTabValue, et al.
|
||||
*/
|
||||
key = "Unique name: " + Math.random();
|
||||
value = "Unique value: " + Date.now();
|
||||
let tab = gBrowser.addTab();
|
||||
|
@ -64,9 +63,9 @@ add_task(function* () {
|
|||
// clean up
|
||||
yield promiseRemoveTab(tab);
|
||||
|
||||
/////////////////////////////////////
|
||||
// getClosedTabCount, undoCloseTab //
|
||||
/////////////////////////////////////
|
||||
/**
|
||||
* getClosedTabCount, undoCloseTab
|
||||
*/
|
||||
|
||||
// get closed tab count
|
||||
let count = ss.getClosedTabCount(window);
|
||||
|
|
|
@ -76,7 +76,7 @@ add_task(function* setup() {
|
|||
document.documentElement.setAttribute("windowtype", "navigator:testrunner");
|
||||
|
||||
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
|
||||
*/
|
||||
function injectTestTabs(win) {
|
||||
TEST_URLS.forEach(function (url) {
|
||||
TEST_URLS.forEach(function(url) {
|
||||
win.gBrowser.addTab(url);
|
||||
});
|
||||
}
|
||||
|
@ -471,4 +471,3 @@ add_task(function* test_mac_notifications() {
|
|||
"Got expected browser-lastwindow-close-granted notifications");
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ add_task(function* () {
|
|||
});
|
||||
|
||||
function promiseSHistoryCount(browser) {
|
||||
/* eslint-env mozilla/frame-script */
|
||||
return ContentTask.spawn(browser, null, function* () {
|
||||
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.
|
||||
ss.setWindowValue(newWin, uniqueKey, uniqueValue);
|
||||
let [txt, chk] = newWin.content.document.querySelectorAll("#txt, #chk");
|
||||
let [txt] = newWin.content.document.querySelectorAll("#txt");
|
||||
txt.value = uniqueText;
|
||||
|
||||
let browser = newWin.gBrowser.selectedBrowser;
|
||||
|
@ -73,7 +73,8 @@ function test() {
|
|||
is(newWin2.gBrowser.currentURI.spec, TEST_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,
|
||||
"The window correctly restored the form");
|
||||
is(ss.getWindowValue(newWin2, uniqueKey), uniqueValue,
|
||||
|
|
|
@ -73,4 +73,4 @@ add_task(function* test_closed_window_states() {
|
|||
other: {popup: 0, normal: 3}};
|
||||
|
||||
yield testWindows(windowsToOpen2, expectedResults2);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,7 +6,7 @@ Components.utils.import("resource://gre/modules/ForgetAboutSite.jsm");
|
|||
|
||||
function waitForClearHistory(aCallback) {
|
||||
let observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
observe(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(this, "browser:purge-domain-data");
|
||||
setTimeout(aCallback, 0);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ function test() {
|
|||
// 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_forward", -1);
|
||||
registerCleanupFunction(function () {
|
||||
registerCleanupFunction(function() {
|
||||
gPrefService.clearUserPref("browser.sessionstore.max_serialize_back");
|
||||
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(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) {
|
||||
|
|
|
@ -24,15 +24,15 @@ function test() {
|
|||
|
||||
frameCount = 0;
|
||||
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
|
||||
if (frameCount++ < 2)
|
||||
return;
|
||||
tab2.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
executeSoon(function() {
|
||||
let iframes = tab2.linkedBrowser.contentWindow.frames;
|
||||
if (iframes[1].document.body.innerHTML !== uniqueValue) {
|
||||
let iframesTab2 = tab2.linkedBrowser.contentWindow.frames;
|
||||
if (iframesTab2[1].document.body.innerHTML !== uniqueValue) {
|
||||
// Poll again the value, since we can't ensure to run
|
||||
// after SessionStore has injected innerHTML value.
|
||||
// See bug 521802.
|
||||
|
@ -41,14 +41,13 @@ function test() {
|
|||
return;
|
||||
}
|
||||
|
||||
is(iframes[1].document.body.innerHTML, uniqueValue,
|
||||
is(iframesTab2[1].document.body.innerHTML, uniqueValue,
|
||||
"rich textarea's content correctly duplicated");
|
||||
|
||||
let innerDomain = null;
|
||||
try {
|
||||
innerDomain = iframes[0].document.domain;
|
||||
}
|
||||
catch (ex) { /* throws for chrome: documents */ }
|
||||
innerDomain = iframesTab2[0].document.domain;
|
||||
} catch (ex) { /* throws for chrome: documents */ }
|
||||
is(innerDomain, "mochi.test", "XSS exploit prevented!");
|
||||
|
||||
// clean up
|
||||
|
|
|
@ -36,6 +36,6 @@
|
|||
});
|
||||
|
||||
frames[1].document.designMode = "on";
|
||||
};
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -26,8 +26,7 @@ function test() {
|
|||
try {
|
||||
aFunction();
|
||||
return false;
|
||||
}
|
||||
catch (ex) {
|
||||
} catch (ex) {
|
||||
return ex.name == "NS_ERROR_ILLEGAL_VALUE";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ function test() {
|
|||
return;
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
let tab2 = gBrowser.duplicateTab(tab);
|
||||
tab2.linkedBrowser.addEventListener("461743", function(aEvent) {
|
||||
tab2.linkedBrowser.addEventListener("461743", function(eventTab2) {
|
||||
tab2.linkedBrowser.removeEventListener("461743", arguments.callee, true);
|
||||
is(aEvent.data, "done", "XSS injection was attempted");
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
xhr.send(null);
|
||||
}
|
||||
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,
|
||||
source: window });
|
||||
document.dispatchEvent(event);
|
||||
|
@ -51,6 +51,6 @@
|
|||
frames[0].document.addEventListener("DOMNodeInserted", done, true);
|
||||
|
||||
frames[0].document.designMode = "on";
|
||||
};
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -35,6 +35,6 @@ add_task(function* test_check_urls_before_restoring() {
|
|||
function getState(url) {
|
||||
return JSON.stringify({
|
||||
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,
|
||||
"", "id prefixes can't be faked");
|
||||
// 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");
|
||||
Assert.equal(content.frames[1].frames[0].document.getElementById("in1").value,
|
||||
"", "id prefixes aren't mixed up");
|
||||
|
|
|
@ -6,7 +6,7 @@ Components.utils.import("resource://gre/modules/ForgetAboutSite.jsm");
|
|||
|
||||
function waitForClearHistory(aCallback) {
|
||||
let observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
observe(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(this, "browser:purge-domain-data");
|
||||
setTimeout(aCallback, 0);
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
}
|
||||
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,
|
||||
source: window });
|
||||
document.dispatchEvent(event);
|
||||
|
|
|
@ -21,7 +21,7 @@ function test() {
|
|||
executeSoon(function() {
|
||||
frameCount = 0;
|
||||
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);
|
||||
is(aEvent.data, "done", "XSS injection was attempted");
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
}
|
||||
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,
|
||||
source: window });
|
||||
document.dispatchEvent(event);
|
||||
|
|
|
@ -21,7 +21,7 @@ function test() {
|
|||
executeSoon(function() {
|
||||
frameCount = 0;
|
||||
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);
|
||||
is(aEvent.data, "done", "XSS injection was attempted");
|
||||
|
||||
|
|
|
@ -12,8 +12,7 @@
|
|||
window.addEventListener("DOMContentLoaded", function() {
|
||||
if (!document.location.hash) {
|
||||
document.location.hash = "#ready";
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
document.getElementById("thief").type = "file";
|
||||
document.getElementById("reverse_thief").type = "text";
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ const STATE3 = createEntries(JSON.stringify(CRASH_STATE));
|
|||
function createEntries(sessionData) {
|
||||
return {
|
||||
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);
|
||||
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.");
|
||||
|
||||
tabState.entries[0].referrer = REFERRER2;
|
||||
|
|
|
@ -73,8 +73,7 @@ function test() {
|
|||
try {
|
||||
aFunction();
|
||||
return false;
|
||||
}
|
||||
catch (ex) {
|
||||
} catch (ex) {
|
||||
return ex.name == "NS_ERROR_ILLEGAL_VALUE";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,13 +12,13 @@ function checkState(tab) {
|
|||
|
||||
let popStateCount = 0;
|
||||
|
||||
tab.linkedBrowser.addEventListener('popstate', function(aEvent) {
|
||||
tab.linkedBrowser.addEventListener("popstate", function(aEvent) {
|
||||
let contentWindow = tab.linkedBrowser.contentWindow;
|
||||
if (popStateCount == 0) {
|
||||
popStateCount++;
|
||||
|
||||
is(tab.linkedBrowser.contentWindow.testState, 'foo',
|
||||
'testState after going back');
|
||||
is(tab.linkedBrowser.contentWindow.testState, "foo",
|
||||
"testState after going back");
|
||||
|
||||
ok(aEvent.state, "Event should have a state property.");
|
||||
is(JSON.stringify(tab.linkedBrowser.contentWindow.history.state), JSON.stringify({obj1:1}),
|
||||
|
@ -33,8 +33,7 @@ function checkState(tab) {
|
|||
doc.body.appendChild(elem);
|
||||
|
||||
tab.linkedBrowser.goForward();
|
||||
}
|
||||
else if (popStateCount == 1) {
|
||||
} else if (popStateCount == 1) {
|
||||
popStateCount++;
|
||||
// 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
|
||||
|
@ -64,7 +63,7 @@ function checkState(tab) {
|
|||
|
||||
// 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.
|
||||
tab.linkedBrowser.contentWindow.testState = 'foo';
|
||||
tab.linkedBrowser.contentWindow.testState = "foo";
|
||||
|
||||
// Now go back. This should trigger the popstate event handler above.
|
||||
tab.linkedBrowser.goBack();
|
||||
|
|
|
@ -19,10 +19,10 @@ function test() {
|
|||
}
|
||||
function getSessionstorejsModificationTime() {
|
||||
let file = getSessionstoreFile();
|
||||
if (file.exists())
|
||||
if (file.exists()) {
|
||||
return file.lastModifiedTime;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// delete existing sessionstore.js, to make sure we're not reading
|
||||
|
@ -49,7 +49,7 @@ function test() {
|
|||
promiseBrowserLoaded(tab.linkedBrowser).then(() => {
|
||||
// step1: the above has triggered some saveStateDelayed(), sleep until
|
||||
// it's done, and get the initial sessionstore.js mtime
|
||||
setTimeout(function step1(e) {
|
||||
setTimeout(function step1() {
|
||||
let mtime1 = getSessionstorejsModificationTime();
|
||||
isnot(mtime1, mtime0, "initial sessionstore.js update");
|
||||
|
||||
|
@ -57,7 +57,7 @@ function test() {
|
|||
// or content scrolling
|
||||
gBrowser.selectedTab = tab;
|
||||
tab.linkedBrowser.contentWindow.scrollTo(1100, 1200);
|
||||
setTimeout(function step2(e) {
|
||||
setTimeout(function step2() {
|
||||
let mtime2 = getSessionstorejsModificationTime();
|
||||
is(mtime2, mtime1,
|
||||
"tab selection and scrolling: sessionstore.js not updated");
|
||||
|
|
|
@ -19,8 +19,8 @@ function test() {
|
|||
};
|
||||
|
||||
var theWin = openDialog(location, "", "chrome,all,dialog=no");
|
||||
theWin.addEventListener("load", function () {
|
||||
executeSoon(function () {
|
||||
theWin.addEventListener("load", function() {
|
||||
executeSoon(function() {
|
||||
var gotError = false;
|
||||
try {
|
||||
ss.setWindowState(theWin, JSON.stringify(state), true);
|
||||
|
|
|
@ -145,7 +145,7 @@ function test() {
|
|||
// be in a non-userTypedValue case, while others should still have
|
||||
// userTypedValue and userTypedClear set.
|
||||
gBrowser.addTabsProgressListener({
|
||||
onLocationChange: function (aBrowser) {
|
||||
onLocationChange(aBrowser) {
|
||||
if (uris.indexOf(aBrowser.currentURI.spec) > -1) {
|
||||
gBrowser.removeTabsProgressListener(this);
|
||||
firstLocationChange();
|
||||
|
@ -194,9 +194,9 @@ function test() {
|
|||
let inputText = "example.org";
|
||||
gURLBar.focus();
|
||||
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",
|
||||
"userTypedValue was set when changing URLBar value");
|
||||
ok(!browser.didStartLoadSinceLastUserTyping(),
|
||||
|
|
|
@ -10,7 +10,7 @@ function test() {
|
|||
|
||||
waitForExplicitFinish();
|
||||
|
||||
whenNewWindowLoaded({ private: false }, function (window_B) {
|
||||
whenNewWindowLoaded({ private: false }, function(window_B) {
|
||||
waitForFocus(function() {
|
||||
// Add identifying information to window_B
|
||||
ss.setWindowValue(window_B, uniqKey, uniqVal);
|
||||
|
|
|
@ -53,12 +53,11 @@ function test() {
|
|||
} else {
|
||||
info("waiting for the current window to become active");
|
||||
setTimeout(pollMostRecentWindow, 0);
|
||||
window.focus(); //XXX Why is this needed?
|
||||
window.focus(); // XXX Why is this needed?
|
||||
}
|
||||
}
|
||||
pollMostRecentWindow();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
browserWindowsCount(1);
|
||||
ok(!window.closed, "Restoring the old state should have left this window open");
|
||||
Services.obs.removeObserver(observer, "sessionstore-browser-state-restored");
|
||||
|
|
|
@ -55,13 +55,13 @@ function openWinWithCb(cb, argURIs, expectedURIs) {
|
|||
var win = openDialog(getBrowserURL(), "_blank",
|
||||
"chrome,all,dialog=no", argURIs.join("|"));
|
||||
|
||||
win.addEventListener("load", function () {
|
||||
win.addEventListener("load", function() {
|
||||
info("the window loaded");
|
||||
|
||||
var expectedLoads = expectedURIs.length;
|
||||
|
||||
win.gBrowser.addTabsProgressListener({
|
||||
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
onStateChange(aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
|
||||
if (aRequest &&
|
||||
aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
|
||||
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
|
||||
|
@ -70,7 +70,7 @@ function openWinWithCb(cb, argURIs, expectedURIs) {
|
|||
win.gBrowser.removeTabsProgressListener(this);
|
||||
info("all tabs loaded");
|
||||
is(win.gBrowser.tabs.length, expectedURIs.length, "didn't load any unexpected tabs");
|
||||
executeSoon(function () {
|
||||
executeSoon(function() {
|
||||
cb(win);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
|
|||
|
||||
add_task(function* test() {
|
||||
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, true);
|
||||
registerCleanupFunction(function () {
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
|
||||
});
|
||||
|
||||
|
@ -24,7 +24,7 @@ add_task(function* test() {
|
|||
|
||||
let loadCount = 0;
|
||||
let promiseRestoringTabs = new Promise(resolve => {
|
||||
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) {
|
||||
gProgressListener.setCallback(function(aBrowser, aNeedRestore, aRestoring, aRestored) {
|
||||
loadCount++;
|
||||
|
||||
// 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_PINNED_TABS_ON_DEMAND, true);
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
|
||||
Services.prefs.clearUserPref(PREF_RESTORE_PINNED_TABS_ON_DEMAND);
|
||||
});
|
||||
|
@ -25,7 +25,7 @@ add_task(function* test() {
|
|||
], selected: 5 }] };
|
||||
|
||||
let promiseRestoringTabs = new Promise(resolve => {
|
||||
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) {
|
||||
gProgressListener.setCallback(function(aBrowser, aNeedRestore, aRestoring, aRestored) {
|
||||
// get the tab
|
||||
let tab;
|
||||
for (let i = 0; i < window.gBrowser.tabs.length; i++) {
|
||||
|
|
|
@ -8,7 +8,7 @@ requestLongerTimeout(2);
|
|||
|
||||
add_task(function* test() {
|
||||
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false);
|
||||
registerCleanupFunction(function () {
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
|
||||
});
|
||||
|
||||
|
@ -63,7 +63,7 @@ add_task(function* test() {
|
|||
|
||||
let loadCount = 0;
|
||||
let promiseRestoringTabs = new Promise(resolve => {
|
||||
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) {
|
||||
gProgressListener.setCallback(function(aBrowser, aNeedRestore, aRestoring, aRestored) {
|
||||
loadCount++;
|
||||
|
||||
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() {
|
||||
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false);
|
||||
registerCleanupFunction(function () {
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
|
||||
});
|
||||
|
||||
|
@ -30,7 +30,7 @@ add_task(function* test() {
|
|||
|
||||
let loadCount = 0;
|
||||
let promiseRestoringTabs = new Promise(resolve => {
|
||||
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) {
|
||||
gProgressListener.setCallback(function(aBrowser, aNeedRestore, aRestoring, aRestored) {
|
||||
loadCount++;
|
||||
let expected = expectedCounts[loadCount - 1];
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
|
|||
|
||||
add_task(function* test() {
|
||||
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false);
|
||||
registerCleanupFunction(function () {
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
|
||||
});
|
||||
|
||||
|
@ -35,7 +35,7 @@ add_task(function* test() {
|
|||
|
||||
let loadCount = 0;
|
||||
let promiseRestoringTabs = new Promise(resolve => {
|
||||
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) {
|
||||
gProgressListener.setCallback(function(aBrowser, aNeedRestore, aRestoring, aRestored) {
|
||||
if (++loadCount == numTabs) {
|
||||
// We don't actually care about load order in this test, just that they all
|
||||
// do load.
|
||||
|
|
|
@ -6,7 +6,7 @@ const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
|
|||
|
||||
add_task(function* test() {
|
||||
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, true);
|
||||
registerCleanupFunction(function () {
|
||||
registerCleanupFunction(function() {
|
||||
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() {
|
||||
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, true);
|
||||
registerCleanupFunction(function () {
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
|
||||
});
|
||||
|
||||
|
@ -31,7 +31,7 @@ add_task(function* test() {
|
|||
|
||||
let loadCount = 0;
|
||||
let promiseRestoringTabs = new Promise(resolve => {
|
||||
gProgressListener.setCallback(function (aBrowser, aNeedRestore, aRestoring, aRestored) {
|
||||
gProgressListener.setCallback(function(aBrowser, aNeedRestore, aRestoring, aRestored) {
|
||||
loadCount++;
|
||||
let expected = expectedCounts[loadCount - 1];
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
|
|||
|
||||
add_task(function* test() {
|
||||
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false);
|
||||
registerCleanupFunction(function () {
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
|
||||
});
|
||||
|
||||
|
@ -30,7 +30,7 @@ add_task(function* test() {
|
|||
|
||||
let loadCount = 0;
|
||||
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
|
||||
if (++loadCount == 2) {
|
||||
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() {
|
||||
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false);
|
||||
registerCleanupFunction(function () {
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
|
||||
});
|
||||
|
||||
|
@ -30,7 +30,7 @@ add_task(function* test() {
|
|||
|
||||
let loadCount = 0;
|
||||
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
|
||||
if (++loadCount == 2) {
|
||||
executeSoon(() => ss.setWindowState(window, JSON.stringify(state2), true));
|
||||
|
|
|
@ -8,7 +8,7 @@ function observeOneRestore(callback) {
|
|||
Services.obs.removeObserver(onRestore, topic);
|
||||
callback();
|
||||
}, topic, false);
|
||||
};
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
@ -37,10 +37,10 @@ function test() {
|
|||
observeOneRestore(function() {
|
||||
let testWindow = Services.wm.getEnumerator("navigator:browser").getNext();
|
||||
is(testWindow.gBrowser.visibleTabs.length, 1, "only restored 1 visible tab");
|
||||
let tabs = testWindow.gBrowser.tabs;
|
||||
ok(!tabs[0].hidden, "first is still visible");
|
||||
ok(tabs[1].hidden, "second tab is still hidden");
|
||||
ok(tabs[2].hidden, "third tab is now hidden");
|
||||
let restoredTabs = testWindow.gBrowser.tabs;
|
||||
ok(!restoredTabs[0].hidden, "first is still visible");
|
||||
ok(restoredTabs[1].hidden, "second tab is still hidden");
|
||||
ok(restoredTabs[2].hidden, "third tab is now hidden");
|
||||
|
||||
// Restore the original state and clean up now that we're done
|
||||
gBrowser.removeTab(hiddenTab);
|
||||
|
|
|
@ -9,7 +9,7 @@ function test() {
|
|||
|
||||
waitForExplicitFinish();
|
||||
|
||||
newWindowWithState(state, function (win) {
|
||||
newWindowWithState(state, function(win) {
|
||||
registerCleanupFunction(() => BrowserTestUtils.closeWindow(win));
|
||||
|
||||
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);
|
||||
|
||||
win.addEventListener("load", function() {
|
||||
executeSoon(function () {
|
||||
executeSoon(function() {
|
||||
win.addEventListener("SSWindowStateReady", function() {
|
||||
promiseTabRestored(win.gBrowser.tabs[0]).then(() => callback(win));
|
||||
}, {once: true});
|
||||
|
|
|
@ -58,7 +58,7 @@ tests.push({
|
|||
extra: false,
|
||||
close: false,
|
||||
checkWinLin: checkNoWindowsGenerator(1),
|
||||
checkOSX: function(aPreviousState, aCurState) {
|
||||
checkOSX(aPreviousState, aCurState) {
|
||||
is(aCurState, aPreviousState, "test #1: closed window state is unchanged");
|
||||
}
|
||||
});
|
||||
|
@ -118,8 +118,7 @@ function test() {
|
|||
function runNextTestOrFinish() {
|
||||
if (tests.length) {
|
||||
setupForTest(tests.shift())
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// some state is cleaned up at the end of each test, but not all
|
||||
["browser.tabs.warnOnClose", "browser.startup.page"].forEach(function(p) {
|
||||
if (gPrefService.prefHasUserValue(p))
|
||||
|
@ -166,7 +165,7 @@ function onStateRestored(aSubject, aTopic, aData) {
|
|||
if (shouldPinTab)
|
||||
newWin.gBrowser.pinTab(newWin.gBrowser.selectedTab);
|
||||
|
||||
newWin.addEventListener("unload", function () {
|
||||
newWin.addEventListener("unload", function() {
|
||||
onWindowUnloaded();
|
||||
}, {once: true});
|
||||
// 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() {
|
||||
if (shouldCloseTab == "one") {
|
||||
newWin.gBrowser.removeTab(newTab2);
|
||||
}
|
||||
else if (shouldCloseTab == "both") {
|
||||
} else if (shouldCloseTab == "both") {
|
||||
newWin.gBrowser.removeTab(newTab);
|
||||
newWin.gBrowser.removeTab(newTab2);
|
||||
}
|
||||
newWin.BrowserTryToCloseWindow();
|
||||
}, {capture: true, once: true});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
newWin.BrowserTryToCloseWindow();
|
||||
}
|
||||
});
|
||||
|
@ -214,7 +211,7 @@ function onWindowUnloaded() {
|
|||
// Now we want to open a new window
|
||||
let newWin = openDialog(location, "_blank", "chrome,all,dialog=no", "about:mozilla");
|
||||
newWin.addEventListener("load", function(aEvent) {
|
||||
newWin.gBrowser.selectedBrowser.addEventListener("load", function () {
|
||||
newWin.gBrowser.selectedBrowser.addEventListener("load", function() {
|
||||
// Good enough for checking the state
|
||||
afterTestCallback(previousClosedWindowData, ss.getClosedWindowData());
|
||||
afterTestCleanup(newWin);
|
||||
|
|
|
@ -11,8 +11,6 @@ function test() {
|
|||
waitForExplicitFinish();
|
||||
requestLongerTimeout(2);
|
||||
|
||||
let startedTest = false;
|
||||
|
||||
// wasLoaded will be used to keep track of tabs that have already had SSTabRestoring
|
||||
// fired for them.
|
||||
let wasLoaded = { };
|
||||
|
@ -87,8 +85,7 @@ function test() {
|
|||
// then the test is successful.
|
||||
try {
|
||||
ss.deleteTabValue(tab, "baz");
|
||||
}
|
||||
catch (e) {
|
||||
} catch (e) {
|
||||
ok(false, "no error calling deleteTabValue - " + e);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,14 +16,14 @@ function test() {
|
|||
|
||||
waitForExplicitFinish();
|
||||
|
||||
newWindowWithState(state, function (win) {
|
||||
newWindowWithState(state, function(win) {
|
||||
registerCleanupFunction(() => BrowserTestUtils.closeWindow(win));
|
||||
|
||||
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");
|
||||
|
||||
executeSoon(function () {
|
||||
waitForFocus(function () {
|
||||
executeSoon(function() {
|
||||
waitForFocus(function() {
|
||||
middleClickTest(win);
|
||||
finish();
|
||||
}, win);
|
||||
|
@ -64,7 +64,7 @@ function newWindowWithState(state, callback) {
|
|||
callback(win);
|
||||
}, {capture: true, once: true});
|
||||
|
||||
executeSoon(function () {
|
||||
executeSoon(function() {
|
||||
ss.setWindowState(win, JSON.stringify(state), true);
|
||||
});
|
||||
}, {once: true});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
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#2", triggeringPrincipal_base64}]},
|
||||
{entries:[{url:"http://example.com#3", triggeringPrincipal_base64}]},
|
||||
|
@ -16,13 +16,13 @@ function test() {
|
|||
waitForExplicitFinish();
|
||||
requestLongerTimeout(2);
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.clearUserPref("browser.sessionstore.restore_hidden_tabs");
|
||||
});
|
||||
|
||||
// First stage: restoreHiddenTabs = true
|
||||
// Second stage: restoreHiddenTabs = false
|
||||
test_loadTabs(true, function () {
|
||||
test_loadTabs(true, function() {
|
||||
test_loadTabs(false, finish);
|
||||
});
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ function test_loadTabs(restoreHiddenTabs, callback) {
|
|||
let expectedTabs = restoreHiddenTabs ? 8 : 4;
|
||||
let firstProgress = true;
|
||||
|
||||
newWindowWithState(state, function (win, needsRestore, isRestoring) {
|
||||
newWindowWithState(windowState, function(win, needsRestore, isRestoring) {
|
||||
if (firstProgress) {
|
||||
firstProgress = false;
|
||||
is(isRestoring, 3, "restoring 3 tabs concurrently");
|
||||
|
@ -56,32 +56,32 @@ function test_loadTabs(restoreHiddenTabs, callback) {
|
|||
}
|
||||
|
||||
var TabsProgressListener = {
|
||||
init: function (win) {
|
||||
init(win) {
|
||||
this.window = win;
|
||||
Services.obs.addObserver(this, "sessionstore-debug-tab-restored", false);
|
||||
},
|
||||
|
||||
uninit: function () {
|
||||
uninit() {
|
||||
Services.obs.removeObserver(this, "sessionstore-debug-tab-restored");
|
||||
|
||||
delete this.window;
|
||||
delete this.callback;
|
||||
},
|
||||
|
||||
setCallback: function (callback) {
|
||||
setCallback(callback) {
|
||||
this.callback = callback;
|
||||
},
|
||||
|
||||
observe: function (browser) {
|
||||
observe(browser) {
|
||||
TabsProgressListener.onRestored(browser);
|
||||
},
|
||||
|
||||
onRestored: function (browser) {
|
||||
onRestored(browser) {
|
||||
if (this.callback && browser.__SS_restoreState == TAB_STATE_RESTORING)
|
||||
this.callback.apply(null, [this.window].concat(this.countTabs()));
|
||||
},
|
||||
|
||||
countTabs: function () {
|
||||
countTabs() {
|
||||
let needsRestore = 0, isRestoring = 0;
|
||||
|
||||
for (let i = 0; i < this.window.gBrowser.tabs.length; i++) {
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче