diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /toolkit/components/sessionstore/SessionStoreFunctions.jsm | |
parent | Initial commit. (diff) | |
download | firefox-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.jsm | 456 |
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 = []; + }, +}; |