Bug 1456391 - Part 2: Add mapFrameTree to sessionstore's Utils.jsm. r=mikedeboer

GeckoView has already started using a slightly modified version of mapFrameTree,
and since ssu.forEachNonDynamicChildFrame() has vastly simplified the process of
correctly using FormData/ScrollPosition.collect() for *all* (non-dynamic) child
frames, we want to use mapFrameTree for Fennec's session store as well.

Therefore, to avoid further duplication of code, we add a common version to the
session store's Utils.jsm module.
We base the code on the GeckoView implementation of mapFrameTree, which has
gained the ability to use callback *arrays*, however we still use ssu.forEach-
NonDynamicChildFrame() like Desktop currently does, instead of simply iterating
over *all* frames.

MozReview-Commit-ID: 3ilEgNSeCEv

--HG--
extra : rebase_source : 793c34bf5160329efd7f92c402945903f0204da9
This commit is contained in:
Jan Henning 2018-04-25 22:04:56 +02:00
Родитель d81f066c59
Коммит 5c6e590a78
1 изменённых файлов: 49 добавлений и 0 удалений

Просмотреть файл

@ -14,6 +14,9 @@ ChromeUtils.defineModuleGetter(this, "NetUtil",
XPCOMUtils.defineLazyServiceGetter(this, "serializationHelper",
"@mozilla.org/network/serialization-helper;1",
"nsISerializationHelper");
XPCOMUtils.defineLazyServiceGetter(this, "ssu",
"@mozilla.org/browser/sessionstore/utils;1",
"nsISessionStoreUtils");
XPCOMUtils.defineLazyGetter(this, "SERIALIZED_SYSTEMPRINCIPAL", function() {
return Utils.serializePrincipal(Services.scriptSecurityManager.getSystemPrincipal());
});
@ -147,5 +150,51 @@ var Utils = Object.freeze({
debug(`Failed to deserialize principal_b64 '${principal_b64}' ${e}`);
}
return null;
},
/**
* A function that will recursively call |cb| to collect data for all
* non-dynamic frames in the current frame/docShell tree.
*
* @param {mozIDOMWindowProxy} frame A DOM window or content frame for which
* data will be collected.
* @param {...function} dataCollectors One or more data collection functions
* that will be called once for each non-
* dynamic frame in the given frame tree,
* and which should return the data they
* wish to save for that respective frame.
* @return {object[]} An array with one entry per dataCollector, containing
* the collected data as a nested data structure according
* to the layout of the frame tree, or null if no data was
* returned by the respective dataCollector.
*/
mapFrameTree(frame, ...dataCollectors) {
// Collect data for the current frame.
let objs = dataCollectors.map((dataCollector) => dataCollector(frame) || {});
let children = dataCollectors.map(() => []);
// Recurse into child frames.
ssu.forEachNonDynamicChildFrame(frame, (subframe, index) => {
let results = this.mapFrameTree(subframe, ...dataCollectors);
if (!results) {
return;
}
for (let j = results.length - 1; j >= 0; --j) {
if (!results[j] || !Object.getOwnPropertyNames(results[j]).length) {
continue;
}
children[j][index] = results[j];
}
});
for (let i = objs.length - 1; i >= 0; --i) {
if (!children[i].length) {
continue;
}
objs[i].children = children[i];
}
return objs.map((obj) => Object.getOwnPropertyNames(obj).length ? obj : null);
}
});