Bug 1379900 - Doing elements filtering in JS to simplify XPath query in FormData::collect. r?mikedeboer
MozReview-Commit-ID: 7VjSkV8dlq1
--- a/toolkit/modules/sessionstore/FormData.jsm
+++ b/toolkit/modules/sessionstore/FormData.jsm
@@ -71,16 +71,32 @@ function isValidCCNumber(value) {
}
} else {
total += currentDigit;
}
}
return total % 10 == 0;
}
+// For a comprehensive list of all available <INPUT> types see
+// https://dxr.mozilla.org/mozilla-central/search?q=kInputTypeTable&redirect=false
+const IGNORE_ATTRIBUTES = [
+ ["type", new Set(["password", "hidden", "button", "image", "submit", "reset"])],
+ ["autocomplete", new Set(["off"])]
+];
+function shouldIgnoreNode(node) {
+ for (let i = 0; i < IGNORE_ATTRIBUTES.length; ++i) {
+ let [attrName, attrValues] = IGNORE_ATTRIBUTES[i];
+ if (node.hasAttribute(attrName) && attrValues.has(node.getAttribute(attrName).toLowerCase())) {
+ return true;
+ }
+ }
+ return false;
+}
+
/**
* The public API exported by this module that allows to collect
* and restore form data for a document and its subframes.
*/
this.FormData = Object.freeze({
collect(frame) {
return FormDataInternal.collect(frame);
},
@@ -113,37 +129,21 @@ var FormDataInternal = {
resolveNS(aPrefix) {
return this.namespaceURIs[aPrefix] || null;
},
/**
* @returns an XPath query to all savable form field nodes
*/
get restorableFormNodesXPath() {
- // for a comprehensive list of all available <INPUT> types see
- // https://dxr.mozilla.org/mozilla-central/search?q=kInputTypeTable&redirect=false
- let ignoreInputs = new Map([
- ["type", ["password", "hidden", "button", "image", "submit", "reset"]],
- ["autocomplete", ["off"]]
- ]);
- // XXXzeniko work-around until lower-case has been implemented (bug 398389)
- let toLowerCase = '"ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz"';
- let ignores = [];
- for (let [attrName, attrValues] of ignoreInputs) {
- for (let attrValue of attrValues)
- ignores.push(`translate(@${attrName}, ${toLowerCase})='${attrValue}'`);
- }
- let ignore = `not(${ignores.join(" or ")})`;
-
- let formNodesXPath = `//textarea[${ignore}]|//xhtml:textarea[${ignore}]|` +
- `//select[${ignore}]|//xhtml:select[${ignore}]|` +
- `//input[${ignore}]|//xhtml:input[${ignore}]`;
-
- // Special case for about:config's search field.
- formNodesXPath += '|/xul:window[@id="config"]//xul:textbox[@id="textbox"]';
+ let formNodesXPath = "//textarea|//xhtml:textarea|" +
+ "//select|//xhtml:select|" +
+ "//input|//xhtml:input" +
+ // Special case for about:config's search field.
+ "|/xul:window[@id='config']//xul:textbox[@id='textbox']";
delete this.restorableFormNodesXPath;
return (this.restorableFormNodesXPath = formNodesXPath);
},
/**
* Collect form data for a given |frame| *not* including any subframes.
*
@@ -179,16 +179,19 @@ var FormDataInternal = {
let ret = {};
// Limit the number of XPath expressions for performance reasons. See
// bug 477564.
const MAX_TRAVERSED_XPATHS = 100;
let generatedCount = 0;
while ((node = formNodes.iterateNext())) {
+ if (shouldIgnoreNode(node)) {
+ continue;
+ }
let hasDefaultValue = true;
let value;
// Only generate a limited number of XPath expressions for perf reasons
// (cf. bug 477564)
if (!node.id && generatedCount > MAX_TRAVERSED_XPATHS) {
continue;
}