Bug 1379900 - Doing elements filtering in JS to simplify XPath query in FormData::collect. r?mikedeboer draft
authorBeekill95 <nnn_bikiu0707@yahoo.com>
Sun, 23 Jul 2017 14:41:52 +0700
changeset 614124 eeaed74704a5a473afa59fd06ec202bbc18ebeb4
parent 613041 417eea89f792059e88be5e217e6f1a5cecf2d3d0
child 638789 739f308bb4816f71c190491c182120605a5679a1
push id69928
push userbmo:nnn_bikiu0707@yahoo.com
push dateMon, 24 Jul 2017 06:54:19 +0000
reviewersmikedeboer
bugs1379900
milestone56.0a1
Bug 1379900 - Doing elements filtering in JS to simplify XPath query in FormData::collect. r?mikedeboer MozReview-Commit-ID: 7VjSkV8dlq1
toolkit/modules/sessionstore/FormData.jsm
--- 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;
       }