Bug 1341582 - Apply form autofill to an already-focused input, r=MattN draft
authorLuke Chang <lchang@mozilla.com>
Thu, 23 Feb 2017 14:44:07 +0800
changeset 488575 1927070bd1398d46176671a2ee04c34e799136ae
parent 487832 a180b976c165b6cd174d24bbb77941919cdc53cb
child 546780 1087b02977a3e925bc4843ea616d11c47680119a
push id46583
push userbmo:lchang@mozilla.com
push dateThu, 23 Feb 2017 10:47:55 +0000
reviewersMattN
bugs1341582
milestone54.0a1
Bug 1341582 - Apply form autofill to an already-focused input, r=MattN MozReview-Commit-ID: C6zT7jKBb4c
browser/extensions/formautofill/FormAutofillContent.jsm
browser/extensions/formautofill/content/FormAutofillFrameScript.js
browser/extensions/formautofill/test/unit/test_getFormInputDetails.js
browser/extensions/formautofill/test/unit/test_markAsAutofillField.js
toolkit/components/satchel/nsFormFillController.cpp
--- a/browser/extensions/formautofill/FormAutofillContent.jsm
+++ b/browser/extensions/formautofill/FormAutofillContent.jsm
@@ -309,18 +309,18 @@ var FormAutofillContent = {
     return formDetails ? formDetails.fieldDetails : null;
   },
 
   getAllFieldNames(element) {
     let formDetails = this.getFormDetails(element);
     return formDetails.map(record => record.fieldName);
   },
 
-  _identifyAutofillFields(doc) {
-    this.log.debug("_identifyAutofillFields:", "" + doc.location);
+  identifyAutofillFields(doc) {
+    this.log.debug("identifyAutofillFields:", "" + doc.location);
     let forms = [];
 
     // Collects root forms from inputs.
     for (let field of doc.getElementsByTagName("input")) {
       // We only consider text-like fields for now until we support radio and
       // checkbox buttons in the future.
       if (!field.mozIsTextField(true)) {
         continue;
--- a/browser/extensions/formautofill/content/FormAutofillFrameScript.js
+++ b/browser/extensions/formautofill/content/FormAutofillFrameScript.js
@@ -7,16 +7,17 @@
  */
 
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://formautofill/FormAutofillContent.jsm");
 
 /**
  * Handles content's interactions for the frame.
  *
  * NOTE: Declares it by "var" to make it accessible in unit tests.
  */
 var FormAutofillFrameScript = {
   init() {
@@ -33,19 +34,16 @@ var FormAutofillFrameScript = {
     }
 
     switch (evt.type) {
       case "DOMContentLoaded": {
         let doc = evt.target;
         if (!(doc instanceof Ci.nsIDOMHTMLDocument)) {
           return;
         }
-        this.FormAutofillContent._identifyAutofillFields(doc);
+        FormAutofillContent.identifyAutofillFields(doc);
         break;
       }
     }
   },
 };
 
-XPCOMUtils.defineLazyModuleGetter(FormAutofillFrameScript, "FormAutofillContent",
-                                  "resource://formautofill/FormAutofillContent.jsm");
-
 FormAutofillFrameScript.init();
--- a/browser/extensions/formautofill/test/unit/test_getFormInputDetails.js
+++ b/browser/extensions/formautofill/test/unit/test_getFormInputDetails.js
@@ -72,17 +72,17 @@ const TESTCASES = [
 
 
 TESTCASES.forEach(testcase => {
   add_task(function* () {
     do_print("Starting testcase: " + testcase.description);
 
     let doc = MockDocument.createTestDocument(
               "http://localhost:8080/test/", testcase.document);
-    FormAutofillContent._identifyAutofillFields(doc);
+    FormAutofillContent.identifyAutofillFields(doc);
 
     for (let i in testcase.targetInput) {
       let input = doc.getElementById(testcase.targetInput[i]);
 
       // Put the input element reference to `element` to make sure the result of
       // `getInputDetails` contains the same input element.
       testcase.expectedResult[i].input.element = input;
       Assert.deepEqual(FormAutofillContent.getInputDetails(input),
--- a/browser/extensions/formautofill/test/unit/test_markAsAutofillField.js
+++ b/browser/extensions/formautofill/test/unit/test_markAsAutofillField.js
@@ -59,14 +59,14 @@ FormAutofillContent._markAsAutofillField
 TESTCASES.forEach(testcase => {
   add_task(function* () {
     do_print("Starting testcase: " + testcase.description);
 
     markedFieldId = [];
 
     let doc = MockDocument.createTestDocument(
       "http://localhost:8080/test/", testcase.document);
-    FormAutofillContent._identifyAutofillFields(doc);
+    FormAutofillContent.identifyAutofillFields(doc);
 
     Assert.deepEqual(markedFieldId, testcase.expectedResult,
       "Check the fields were marked correctly.");
   });
 });
--- a/toolkit/components/satchel/nsFormFillController.cpp
+++ b/toolkit/components/satchel/nsFormFillController.cpp
@@ -304,19 +304,33 @@ NS_IMETHODIMP
 nsFormFillController::MarkAsAutofillField(nsIDOMHTMLInputElement *aInput)
 {
   /*
    * Support other components implementing form autofill and handle autocomplete
    * for the field.
    */
   nsCOMPtr<nsINode> node = do_QueryInterface(aInput);
   NS_ENSURE_STATE(node);
+
+  if (mAutofillInputs.Get(node)) {
+    return NS_OK;
+  }
+
   mAutofillInputs.Put(node, true);
   node->AddMutationObserverUnlessExists(this);
 
+  nsFocusManager *fm = nsFocusManager::GetFocusManager();
+  if (fm) {
+    nsCOMPtr<nsIContent> focusedContent = fm->GetFocusedContent();
+    if (SameCOMIdentity(focusedContent, node)) {
+      nsCOMPtr<nsIDOMHTMLInputElement> input = do_QueryInterface(node);
+      MaybeStartControllingInput(input);
+    }
+  }
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFormFillController::GetFocusedInput(nsIDOMHTMLInputElement **aInput) {
   *aInput = mFocusedInput;
   NS_IF_ADDREF(*aInput);
   return NS_OK;