summaryrefslogtreecommitdiffstats
path: root/toolkit/components/sessionstore/SessionStoreFunctions.jsm
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /toolkit/components/sessionstore/SessionStoreFunctions.jsm
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/sessionstore/SessionStoreFunctions.jsm')
-rw-r--r--toolkit/components/sessionstore/SessionStoreFunctions.jsm456
1 files changed, 456 insertions, 0 deletions
diff --git a/toolkit/components/sessionstore/SessionStoreFunctions.jsm b/toolkit/components/sessionstore/SessionStoreFunctions.jsm
new file mode 100644
index 0000000000..fc5f73651a
--- /dev/null
+++ b/toolkit/components/sessionstore/SessionStoreFunctions.jsm
@@ -0,0 +1,456 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
+ * 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/. */
+ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm", this);
+
+XPCOMUtils.defineLazyModuleGetters(this, {
+ SessionStore: "resource:///modules/sessionstore/SessionStore.jsm",
+});
+
+function UpdateSessionStore(
+ aBrowser,
+ aBrowsingContext,
+ aFlushId,
+ aIsFinal,
+ aEpoch,
+ aData,
+ aCollectSHistory
+) {
+ return SessionStoreFuncInternal.updateSessionStore(
+ aBrowser,
+ aBrowsingContext,
+ aFlushId,
+ aIsFinal,
+ aEpoch,
+ aData,
+ aCollectSHistory
+ );
+}
+
+var EXPORTED_SYMBOLS = ["UpdateSessionStore"];
+
+var SessionStoreFuncInternal = {
+ // form data which is waiting to be updated
+ _formDataId: [],
+ _formDataIdValue: [],
+ _formDataXPath: [],
+ _formDataXPathValue: [],
+
+ /**
+ * The data will be stored in the arrays:
+ * "_formDataId, _formDataIdValue" for the elements with id.
+ * "_formDataXPath, _formDataXPathValue" for the elements with XPath.
+ */
+ updateFormData: function SSF_updateFormData(aType, aData) {
+ let idArray = this._formDataId;
+ let valueArray = this._formDataIdValue;
+
+ if (aType == "XPath") {
+ idArray = this._formDataXPath;
+ valueArray = this._formDataXPathValue;
+ }
+
+ let valueIdx = aData.valueIdx;
+ for (let i = 0; i < aData.id.length; i++) {
+ idArray.push(aData.id[i]);
+
+ if (aData.type[i] == "singleSelect") {
+ valueArray.push({
+ selectedIndex: aData.selectedIndex[valueIdx[i]],
+ value: aData.selectVal[valueIdx[i]],
+ });
+ } else if (aData.type[i] == "file") {
+ valueArray.push({
+ type: "file",
+ fileList: aData.strVal.slice(valueIdx[i], valueIdx[++i]),
+ });
+ } else if (aData.type[i] == "multipleSelect") {
+ valueArray.push(aData.strVal.slice(valueIdx[i], valueIdx[++i]));
+ } else if (aData.type[i] == "string") {
+ valueArray.push(aData.strVal[valueIdx[i]]);
+ } else if (aData.type[i] == "bool") {
+ valueArray.push(aData.boolVal[valueIdx[i]]);
+ }
+ }
+ },
+
+ /**
+ * Return the array of formdata for this._sessionData.formdata.children
+ *
+ * aStartIndex: Current index for aInnerHTML/aUrl/aNumId/aNumXPath/aDescendants.
+ * (aStartIndex means the index of current root frame)
+ * aInnerHTML: Array for innerHTML.
+ * aUrl: Array for url.
+ * aNumId: Array for number of containing elements with id
+ * aNumXPath: Array for number of containing elements with XPath
+ * aDescendants: Array for number of descendants.
+ *
+ * aCurrentIdIdx: Current index for this._formDataId and this._formDataIdValue
+ * aCurrentXPathIdx: Current index for this._formDataXPath and this._formDataXPathValue
+ * aNumberOfDescendants: The number of descendants for current frame
+ *
+ * The returned array includes "aNumberOfDescendants" formdata objects.
+ */
+ composeInputChildren: function SSF_composeInputChildren(
+ aInnerHTML,
+ aUrl,
+ aCurrentIdIdx,
+ aNumId,
+ aCurrentXpathIdx,
+ aNumXPath,
+ aDescendants,
+ aStartIndex,
+ aNumberOfDescendants
+ ) {
+ let children = [];
+ let lastIndexOfNonNullbject = -1;
+ for (let i = 0; i < aNumberOfDescendants; i++) {
+ let currentIndex = aStartIndex + i;
+ let obj = {};
+ let objWithData = false;
+
+ // set url/id/xpath
+ if (aUrl[currentIndex]) {
+ obj.url = aUrl[currentIndex];
+ objWithData = true;
+
+ if (aInnerHTML[currentIndex]) {
+ // eslint-disable-next-line no-unsanitized/property
+ obj.innerHTML = aInnerHTML[currentIndex];
+ }
+ if (aNumId[currentIndex]) {
+ let idObj = {};
+ for (let idx = 0; idx < aNumId[currentIndex]; idx++) {
+ idObj[
+ this._formDataId[aCurrentIdIdx + idx]
+ ] = this._formDataIdValue[aCurrentIdIdx + idx];
+ }
+ obj.id = idObj;
+ }
+
+ // We want to avoid saving data for about:sessionrestore as a string.
+ // Since it's stored in the form as stringified JSON, stringifying further
+ // causes an explosion of escape characters. cf. bug 467409
+ if (
+ obj.url == "about:sessionrestore" ||
+ obj.url == "about:welcomeback"
+ ) {
+ obj.id.sessionData = JSON.parse(obj.id.sessionData);
+ }
+
+ if (aNumXPath[currentIndex]) {
+ let xpathObj = {};
+ for (let idx = 0; idx < aNumXPath[currentIndex]; idx++) {
+ xpathObj[
+ this._formDataXPath[aCurrentXpathIdx + idx]
+ ] = this._formDataXPathValue[aCurrentXpathIdx + idx];
+ }
+ obj.xpath = xpathObj;
+ }
+ }
+
+ // compose the descendantsTree which will be pushed into children array
+ if (aDescendants[currentIndex]) {
+ let descendantsTree = this.composeInputChildren(
+ aInnerHTML,
+ aUrl,
+ aCurrentIdIdx + aNumId[currentIndex],
+ aNumId,
+ aCurrentXpathIdx + aNumXPath[currentIndex],
+ aNumXPath,
+ aDescendants,
+ currentIndex + 1,
+ aDescendants[currentIndex]
+ );
+ i += aDescendants[currentIndex];
+ if (descendantsTree) {
+ obj.children = descendantsTree;
+ }
+ }
+
+ if (objWithData) {
+ lastIndexOfNonNullbject = children.length;
+ children.push(obj);
+ } else {
+ children.push(null);
+ }
+ }
+
+ if (lastIndexOfNonNullbject == -1) {
+ return null;
+ }
+
+ return children.slice(0, lastIndexOfNonNullbject + 1);
+ },
+
+ /**
+ * Update the object for this._sessionData.formdata.
+ * The object contains the formdata for all reachable frames.
+ *
+ * "object.children" is an array with one entry per frame,
+ * containing formdata as a nested data structure according
+ * to the layout of the frame tree, or null if no formdata.
+ *
+ * Example:
+ * {
+ * url: "http://mozilla.org/",
+ * id: {input_id: "input value"},
+ * xpath: {input_xpath: "input value"},
+ * children: [
+ * null,
+ * {url: "http://sub.mozilla.org/", id: {input_id: "input value 2"}}
+ * ]
+ * }
+ *
+ * Each index of the following array is corresponging to each frame.
+ * aDescendants: Array for number of descendants
+ * aInnerHTML: Array for innerHTML
+ * aUrl: Array for url
+ * aNumId: Array for number of containing elements with id
+ * aNumXPath: Array for number of containing elements with XPath
+ *
+ * Here we use [index 0] to compose the formdata object of root frame.
+ * Besides, we use composeInputChildren() to get array of "object.children".
+ */
+ updateInput: function SSF_updateInput(
+ aSessionData,
+ aDescendants,
+ aInnerHTML,
+ aUrl,
+ aNumId,
+ aNumXPath
+ ) {
+ let obj = {};
+ let objWithData = false;
+
+ if (aUrl[0]) {
+ obj.url = aUrl[0];
+
+ if (aInnerHTML[0]) {
+ // eslint-disable-next-line no-unsanitized/property
+ obj.innerHTML = aInnerHTML[0];
+ objWithData = true;
+ }
+
+ if (aNumId[0]) {
+ let idObj = {};
+ for (let i = 0; i < aNumId[0]; i++) {
+ idObj[this._formDataId[i]] = this._formDataIdValue[i];
+ }
+ obj.id = idObj;
+ objWithData = true;
+ }
+
+ // We want to avoid saving data for about:sessionrestore as a string.
+ // Since it's stored in the form as stringified JSON, stringifying further
+ // causes an explosion of escape characters. cf. bug 467409
+ if (obj.url == "about:sessionrestore" || obj.url == "about:welcomeback") {
+ obj.id.sessionData = JSON.parse(obj.id.sessionData);
+ }
+
+ if (aNumXPath[0]) {
+ let xpathObj = {};
+ for (let i = 0; i < aNumXPath[0]; i++) {
+ xpathObj[this._formDataXPath[i]] = this._formDataXPathValue[i];
+ }
+ obj.xpath = xpathObj;
+ objWithData = true;
+ }
+ }
+
+ if (aDescendants.length > 1) {
+ let descendantsTree = this.composeInputChildren(
+ aInnerHTML,
+ aUrl,
+ aNumId[0],
+ aNumId,
+ aNumXPath[0],
+ aNumXPath,
+ aDescendants,
+ 1,
+ aDescendants[0]
+ );
+ if (descendantsTree) {
+ obj.children = descendantsTree;
+ objWithData = true;
+ }
+ }
+
+ if (objWithData) {
+ aSessionData.formdata = obj;
+ } else {
+ aSessionData.formdata = null;
+ }
+ },
+
+ composeChildren: function SSF_composeScrollPositionsData(
+ aPositions,
+ aDescendants,
+ aStartIndex,
+ aNumberOfDescendants
+ ) {
+ let children = [];
+ let lastIndexOfNonNullbject = -1;
+ for (let i = 0; i < aNumberOfDescendants; i++) {
+ let currentIndex = aStartIndex + i;
+ let obj = {};
+ let objWithData = false;
+ if (aPositions[currentIndex]) {
+ obj.scroll = aPositions[currentIndex];
+ objWithData = true;
+ }
+ if (aDescendants[currentIndex]) {
+ let descendantsTree = this.composeChildren(
+ aPositions,
+ aDescendants,
+ currentIndex + 1,
+ aDescendants[currentIndex]
+ );
+ i += aDescendants[currentIndex];
+ if (descendantsTree) {
+ obj.children = descendantsTree;
+ objWithData = true;
+ }
+ }
+
+ if (objWithData) {
+ lastIndexOfNonNullbject = children.length;
+ children.push(obj);
+ } else {
+ children.push(null);
+ }
+ }
+
+ if (lastIndexOfNonNullbject == -1) {
+ return null;
+ }
+
+ return children.slice(0, lastIndexOfNonNullbject + 1);
+ },
+
+ updateScrollPositions: function SSF_updateScrollPositions(
+ aPositions,
+ aDescendants
+ ) {
+ let obj = {};
+ let objWithData = false;
+
+ if (aPositions[0]) {
+ obj.scroll = aPositions[0];
+ objWithData = true;
+ }
+
+ if (aPositions.length > 1) {
+ let children = this.composeChildren(
+ aPositions,
+ aDescendants,
+ 1,
+ aDescendants[0]
+ );
+ if (children) {
+ obj.children = children;
+ objWithData = true;
+ }
+ }
+ if (objWithData) {
+ return obj;
+ }
+ return null;
+ },
+
+ updateStorage: function SSF_updateStorage(aOrigins, aKeys, aValues) {
+ let data = {};
+ for (let i = 0; i < aOrigins.length; i++) {
+ // If the key isn't defined, then .clear() was called, and we send
+ // up null for this domain to indicate that storage has been cleared
+ // for it.
+ if (aKeys[i] == "") {
+ while (aOrigins[i + 1] == aOrigins[i]) {
+ i++;
+ }
+ data[aOrigins[i]] = null;
+ } else {
+ let hostData = {};
+ hostData[aKeys[i]] = aValues[i];
+ while (aOrigins[i + 1] == aOrigins[i]) {
+ i++;
+ hostData[aKeys[i]] = aValues[i];
+ }
+ data[aOrigins[i]] = hostData;
+ }
+ }
+ if (aOrigins.length) {
+ return data;
+ }
+
+ return null;
+ },
+
+ updateSessionStore: function SSF_updateSessionStore(
+ aBrowser,
+ aBrowsingContext,
+ aFlushId,
+ aIsFinal,
+ aEpoch,
+ aData,
+ aCollectSHistory
+ ) {
+ let currentData = {};
+ if (aData.docShellCaps != undefined) {
+ currentData.disallow = aData.docShellCaps ? aData.docShellCaps : null;
+ }
+ if (aData.isPrivate != undefined) {
+ currentData.isPrivate = aData.isPrivate;
+ }
+ if (
+ aData.positions != undefined &&
+ aData.positionDescendants != undefined
+ ) {
+ currentData.scroll = this.updateScrollPositions(
+ aData.positions,
+ aData.positionDescendants
+ );
+ }
+ if (aData.id != undefined) {
+ this.updateFormData("id", aData.id);
+ }
+ if (aData.xpath != undefined) {
+ this.updateFormData("XPath", aData.xpath);
+ }
+ if (aData.inputDescendants != undefined) {
+ this.updateInput(
+ currentData,
+ aData.inputDescendants,
+ aData.innerHTML,
+ aData.url,
+ aData.numId,
+ aData.numXPath
+ );
+ }
+ if (aData.isFullStorage != undefined) {
+ let storage = this.updateStorage(
+ aData.storageOrigins,
+ aData.storageKeys,
+ aData.storageValues
+ );
+ if (aData.isFullStorage) {
+ currentData.storage = storage;
+ } else {
+ currentData.storagechange = storage;
+ }
+ }
+
+ SessionStore.updateSessionStoreFromTablistener(aBrowser, aBrowsingContext, {
+ data: currentData,
+ flushID: aFlushId,
+ isFinal: aIsFinal,
+ epoch: aEpoch,
+ sHistoryNeeded: aCollectSHistory,
+ });
+ this._formDataId = [];
+ this._formDataIdValue = [];
+ this._formDataXPath = [];
+ this._formDataXPathValue = [];
+ },
+};