Bug 1415739 - Use type/autocomplete properties, instead of attributes, to decide whether to save FormData. r=mikedeboer draft
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Wed, 22 Nov 2017 16:37:40 -0500
changeset 702202 13b94e29dc0a32185d9fcb60e503988a722ea60a
parent 702201 019c7b6b48a1aaf3e05b05c49fda9917523c20cc
child 741401 4fdb29cfe4f8244e93ec7f5e08a85da9d70caece
push id90414
push usermozilla@noorenberghe.ca
push dateWed, 22 Nov 2017 21:44:13 +0000
reviewersmikedeboer
bugs1415739
milestone59.0a1
Bug 1415739 - Use type/autocomplete properties, instead of attributes, to decide whether to save FormData. r=mikedeboer The property values are already normalized according to the spec. MozReview-Commit-ID: DbKZf9KXCji
browser/components/sessionstore/test/browser_456342.js
browser/components/sessionstore/test/browser_456342_sample.xhtml
toolkit/modules/sessionstore/FormData.jsm
--- a/browser/components/sessionstore/test/browser_456342.js
+++ b/browser/components/sessionstore/test/browser_456342.js
@@ -1,15 +1,26 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 const URL = ROOT + "browser_456342_sample.xhtml";
 
+const EXPECTED_IDS = new Set([
+  "searchTerm",
+]);
+
+const EXPECTED_XPATHS = new Set([
+  "/xhtml:html/xhtml:body/xhtml:form/xhtml:p[2]/xhtml:input",
+  "/xhtml:html/xhtml:body/xhtml:form/xhtml:p[3]/xhtml:input[@name='fill-in']",
+  "/xhtml:html/xhtml:body/xhtml:form/xhtml:p[4]/xhtml:input[@name='mistyped']",
+  "/xhtml:html/xhtml:body/xhtml:form/xhtml:p[5]/xhtml:textarea[@name='textarea_pass']",
+]);
+
 /**
  * Bug 456342 - Restore values from non-standard input field types.
  */
 add_task(async function test_restore_nonstandard_input_values() {
   // Add tab with various non-standard input field types.
   let tab = BrowserTestUtils.addTab(gBrowser, URL);
   let browser = tab.linkedBrowser;
   await promiseBrowserLoaded(browser);
@@ -18,32 +29,29 @@ add_task(async function test_restore_non
   let expectedValue = Math.random();
   await setFormElementValues(browser, {value: expectedValue});
 
   // Remove tab and check collected form data.
   await promiseRemoveTab(tab);
   let undoItems = JSON.parse(ss.getClosedTabData(window));
   let savedFormData = undoItems[0].state.formdata;
 
-  let countGood = 0, countBad = 0;
+  let foundIds = 0;
   for (let id of Object.keys(savedFormData.id)) {
-    if (savedFormData.id[id] == expectedValue) {
-      countGood++;
-    } else {
-      countBad++;
-    }
+    ok(EXPECTED_IDS.has(id), `Check saved ID "${id}" was expected`);
+    is(savedFormData.id[id], expectedValue, `Check saved value for #${id}`);
+    foundIds++;
   }
 
+  let foundXpaths = 0;
   for (let exp of Object.keys(savedFormData.xpath)) {
-    if (savedFormData.xpath[exp] == expectedValue) {
-      countGood++;
-    } else {
-      countBad++;
-    }
+    ok(EXPECTED_XPATHS.has(exp), `Check saved xpath "${exp}" was expected`);
+    is(savedFormData.xpath[exp], expectedValue, `Check saved value for ${exp}`);
+    foundXpaths++;
   }
 
-  is(countGood, 4, "Saved text for non-standard input fields");
-  is(countBad, 0, "Didn't save text for ignored field types");
+  is(foundIds, EXPECTED_IDS.size, "Check number of fields saved by ID");
+  is(foundXpaths, EXPECTED_XPATHS.size, "Check number of fields saved by xpath");
 });
 
 function setFormElementValues(browser, data) {
   return sendMessage(browser, "ss-test:setFormElementValues", data);
 }
--- a/browser/components/sessionstore/test/browser_456342_sample.xhtml
+++ b/browser/components/sessionstore/test/browser_456342_sample.xhtml
@@ -6,29 +6,32 @@
 
 <body>
 <form>
 <h3>Non-standard &lt;input&gt;s</h3>
 <p>Search        <input type="search"       id="searchTerm"/></p>
 <p>Image Search: <input type="image search" /></p>
 <p>Autocomplete: <input type="autocomplete" name="fill-in"/></p>
 <p>Mistyped:     <input type="txet"         name="mistyped"/></p>
+<p>Invalid attr: <textarea type="password" name="textarea_pass"/></p>
 
 <h3>Ignored types</h3>
 <input type="hidden" name="hideme"/>
 <input type="HIDDEN" name="hideme2"/>
 <input type="submit" name="submit"/>
 <input type="reset"  name="reset"/>
 <input type="image"  name="image"/>
 <input type="button" name="button"/>
 <input type="password" name="password"/>
 <input type="PassWord" name="password2"/>
 <input type="PASSWORD" name="password3"/>
 <input autocomplete="off" name="auto1"/>
 <input type="text" autocomplete="OFF" name="auto2"/>
+<input type="text" autocomplete="   OFF   " name="auto5"/>
+<input autocomplete="   off   " name="auto6"/>
 <textarea autocomplete="off" name="auto3"/>
 <select autocomplete="off" name="auto4">
   <option value="1" selected="true"/>
   <option value="2"/>
   <option value="3"/>
 </select>
 </form>
 
--- a/toolkit/modules/sessionstore/FormData.jsm
+++ b/toolkit/modules/sessionstore/FormData.jsm
@@ -73,24 +73,24 @@ function isValidCCNumber(value) {
       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 = [
+const IGNORE_PROPERTIES = [
   ["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())) {
+  for (let i = 0; i < IGNORE_PROPERTIES.length; ++i) {
+    let [propName, propValues] = IGNORE_PROPERTIES[i];
+    if (node[propName] && propValues.has(node[propName])) {
       return true;
     }
   }
   return false;
 }
 
 /**
  * The public API exported by this module that allows to collect