Bug 1300988 - Part 1: Add FormAutoFillHandler instance and collectFormFields/autofillFormFields methods. r=MattN draft
authorSteve Chung <schung@mozilla.com>
Tue, 20 Sep 2016 11:55:24 +0800
changeset 426802 1c5279fc5590ec2159b4b2a19c40ba2d84539c61
parent 426771 90d8afaddf9150853b0b68b35b30c1e54a8683e7
child 426803 bf23ad4432cc9a30fb1295dd6ed688a11ab597e3
push id32805
push userschung@mozilla.com
push dateWed, 19 Oct 2016 05:07:51 +0000
reviewersMattN
bugs1300988
milestone52.0a1
Bug 1300988 - Part 1: Add FormAutoFillHandler instance and collectFormFields/autofillFormFields methods. r=MattN MozReview-Commit-ID: Jmy7WMqyFUB
browser/extensions/formautofill/content/FormAutofillContent.jsm
browser/extensions/formautofill/jar.mn
browser/extensions/formautofill/moz.build
new file mode 100644
--- /dev/null
+++ b/browser/extensions/formautofill/content/FormAutofillContent.jsm
@@ -0,0 +1,134 @@
+/* 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/. */
+
+/*
+ * Implements a service used by DOM content to request Form Autofill.
+ */
+
+"use strict";
+
+const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
+
+/**
+ * Handles profile autofill for a DOM Form element.
+ * @param {HTMLFormElement} form Form that need to be auto filled
+ */
+function FormAutofillHandler(form) {
+  this.form = form;
+  this.fieldDetails = [];
+}
+
+FormAutofillHandler.prototype = {
+  /**
+   * DOM Form element to which this object is attached.
+   */
+  form: null,
+
+  /**
+   * Array of collected data about relevant form fields.  Each item is an object
+   * storing the identifying details of the field and a reference to the
+   * originally associated element from the form.
+   *
+   * The "section", "addressType", "contactType", and "fieldName" values are
+   * used to identify the exact field when the serializable data is received
+   * from the backend.  There cannot be multiple fields which have
+   * the same exact combination of these values.
+   *
+   * A direct reference to the associated element cannot be sent to the user
+   * interface because processing may be done in the parent process.
+   */
+  fieldDetails: null,
+
+  /**
+   * Returns information from the form about fields that can be autofilled, and
+   * populates the fieldDetails array on this object accordingly.
+   *
+   * @returns {Array<Object>} Serializable data structure that can be sent to the user
+   *          interface, or null if the operation failed because the constraints
+   *          on the allowed fields were not honored.
+   */
+  collectFormFields() {
+    let autofillData = [];
+
+    for (let element of this.form.elements) {
+      // Query the interface and exclude elements that cannot be autocompleted.
+      if (!(element instanceof Ci.nsIDOMHTMLInputElement)) {
+        continue;
+      }
+
+      // Exclude elements to which no autocomplete field has been assigned.
+      let info = element.getAutocompleteInfo();
+      if (!info.fieldName || ["on", "off"].includes(info.fieldName)) {
+        continue;
+      }
+
+      // Store the association between the field metadata and the element.
+      if (this.fieldDetails.some(f => f.section == info.section &&
+                                      f.addressType == info.addressType &&
+                                      f.contactType == info.contactType &&
+                                      f.fieldName == info.fieldName)) {
+        // A field with the same identifier already exists.
+        return null;
+      }
+
+      let inputFormat = {
+        section: info.section,
+        addressType: info.addressType,
+        contactType: info.contactType,
+        fieldName: info.fieldName,
+      };
+      // Clone the inputFormat for caching the fields and elements together
+      let formatWithElement = Object.assign({}, inputFormat);
+
+      inputFormat.index = autofillData.length;
+      autofillData.push(inputFormat);
+
+      formatWithElement.element = element;
+      this.fieldDetails.push(formatWithElement);
+    }
+
+    return autofillData;
+  },
+
+  /**
+   * Processes form fields that can be autofilled, and populates them with the
+   * data provided by backend.
+   *
+   * @param {Array<Object>} autofillResult
+   *        Data returned by the user interface.
+   *        [{
+   *          section: Value originally provided to the user interface.
+   *          addressType: Value originally provided to the user interface.
+   *          contactType: Value originally provided to the user interface.
+   *          fieldName: Value originally provided to the user interface.
+   *          value: String with which the field should be updated.
+   *          index: Index to match the input in fieldDetails
+   *        }],
+   *        }
+   */
+  autofillFormFields(autofillResult) {
+    for (let field of autofillResult) {
+      // Get the field details, if it was processed by the user interface.
+      let fieldDetail = this.fieldDetails[field.index];
+
+      // Avoid the invalid value set
+      if (!fieldDetail || !field.value) {
+        continue;
+      }
+
+      let info = fieldDetail.element.getAutocompleteInfo();
+      if (field.section != info.section ||
+          field.addressType != info.addressType ||
+          field.contactType != info.contactType ||
+          field.fieldName != info.fieldName) {
+        Cu.reportError("Autocomplete tokens mismatched");
+        continue;
+      }
+
+      fieldDetail.element.setUserInput(field.value);
+    }
+  },
+};
+
+this.EXPORTED_SYMBOLS = ["FormAutofillHandler"];
new file mode 100644
--- /dev/null
+++ b/browser/extensions/formautofill/jar.mn
@@ -0,0 +1,7 @@
+# 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/.
+
+[features/formautofill@mozilla.org] chrome.jar:
+% resource formautofill %content/
+ content/ (content/*)
--- a/browser/extensions/formautofill/moz.build
+++ b/browser/extensions/formautofill/moz.build
@@ -11,8 +11,11 @@ FINAL_TARGET_FILES.features['formautofil
   'bootstrap.js'
 ]
 
 FINAL_TARGET_PP_FILES.features['formautofill@mozilla.org'] += [
   'install.rdf.in'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
+
+JAR_MANIFESTS += ['jar.mn']
+