Bug 1340468 - Notify formautofill add-on of which item is being selected. r=MattN
MozReview-Commit-ID: 3YfW35Zon1Q
--- a/browser/extensions/formautofill/FormAutofillContent.jsm
+++ b/browser/extensions/formautofill/FormAutofillContent.jsm
@@ -158,16 +158,17 @@ AutofillProfileAutoCompleteSearch.protot
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([AutofillProfileAutoCompleteSearch]);
let ProfileAutocomplete = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
_lastAutoCompleteResult: null,
+ _lastAutoCompleteFocusedInput: null,
_registered: false,
_factory: null,
ensureRegistered() {
if (this._registered) {
return;
}
@@ -191,16 +192,17 @@ let ProfileAutocomplete = {
this._registered = false;
this._lastAutoCompleteResult = null;
Services.obs.removeObserver(this, "autocomplete-will-enter-text");
},
setProfileAutoCompleteResult(result) {
this._lastAutoCompleteResult = result;
+ this._lastAutoCompleteFocusedInput = formFillController.focusedInput;
},
observe(subject, topic, data) {
switch (topic) {
case "autocomplete-will-enter-text": {
if (!formFillController.focusedInput) {
// The observer notification is for autocomplete in a different process.
break;
@@ -213,42 +215,75 @@ let ProfileAutocomplete = {
_frameMMFromWindow(contentWindow) {
return contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell)
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIContentFrameMessageManager);
},
+ _getSelectedIndex(contentWindow) {
+ let mm = this._frameMMFromWindow(contentWindow);
+ let selectedIndexResult = mm.sendSyncMessage("FormAutoComplete:GetSelectedIndex", {});
+ if (selectedIndexResult.length != 1 || !Number.isInteger(selectedIndexResult[0])) {
+ throw new Error("Invalid autocomplete selectedIndex");
+ }
+
+ return selectedIndexResult[0];
+ },
+
_fillFromAutocompleteRow(focusedInput) {
this.log.debug("_fillFromAutocompleteRow:", focusedInput);
let formDetails = FormAutofillContent.getFormDetails(focusedInput);
if (!formDetails) {
// The observer notification is for a different frame.
return;
}
- let mm = this._frameMMFromWindow(focusedInput.ownerGlobal);
- let selectedIndexResult = mm.sendSyncMessage("FormAutoComplete:GetSelectedIndex", {});
- if (selectedIndexResult.length != 1 || !Number.isInteger(selectedIndexResult[0])) {
- throw new Error("Invalid autocomplete selectedIndex");
- }
- let selectedIndex = selectedIndexResult[0];
-
+ let selectedIndex = this._getSelectedIndex(focusedInput.ownerGlobal);
if (selectedIndex == -1 ||
!this._lastAutoCompleteResult ||
this._lastAutoCompleteResult.getStyleAt(selectedIndex) != "autofill-profile") {
return;
}
let profile = JSON.parse(this._lastAutoCompleteResult.getCommentAt(selectedIndex));
let formHandler = FormAutofillContent.getFormHandler(focusedInput);
formHandler.autofillFormFields(profile, focusedInput);
},
+
+ _clearProfilePreview() {
+ let focusedInput = formFillController.focusedInput || this._lastAutoCompleteFocusedInput;
+ if (!focusedInput || !FormAutofillContent.getFormDetails(focusedInput)) {
+ return;
+ }
+
+ let formHandler = FormAutofillContent.getFormHandler(focusedInput);
+
+ formHandler.clearPreviewedFormFields();
+ },
+
+ _previewSelectedProfile(selectedIndex) {
+ let focusedInput = formFillController.focusedInput;
+ if (!focusedInput || !FormAutofillContent.getFormDetails(focusedInput)) {
+ // The observer notification is for a different process/frame.
+ return;
+ }
+
+ if (!this._lastAutoCompleteResult ||
+ this._lastAutoCompleteResult.getStyleAt(selectedIndex) != "autofill-profile") {
+ return;
+ }
+
+ let profile = JSON.parse(this._lastAutoCompleteResult.getCommentAt(selectedIndex));
+ let formHandler = FormAutofillContent.getFormHandler(focusedInput);
+
+ formHandler.previewFormFields(profile);
+ },
};
/**
* Handles content's interactions for the process.
*
* NOTE: Declares it by "var" to make it accessible in unit tests.
*/
var FormAutofillContent = {
@@ -378,12 +413,22 @@ var FormAutofillContent = {
this.log.debug("Adding form handler to _formsDetails:", formHandler);
formHandler.fieldDetails.forEach(detail => this._markAsAutofillField(detail.element));
});
},
_markAsAutofillField(field) {
formFillController.markAsAutofillField(field);
},
+
+ _previewProfile(doc) {
+ let selectedIndex = ProfileAutocomplete._getSelectedIndex(doc.ownerGlobal);
+
+ if (selectedIndex === -1) {
+ ProfileAutocomplete._clearProfilePreview();
+ } else {
+ ProfileAutocomplete._previewSelectedProfile(selectedIndex);
+ }
+ },
};
FormAutofillContent.init();
--- a/browser/extensions/formautofill/FormAutofillHandler.jsm
+++ b/browser/extensions/formautofill/FormAutofillHandler.jsm
@@ -119,9 +119,46 @@ FormAutofillHandler.prototype = {
}
let value = profile[fieldDetail.fieldName];
if (value) {
fieldDetail.element.setUserInput(value);
}
}
},
+
+ /**
+ * Populates result to the preview layers with given profile.
+ *
+ * @param {Object} profile
+ * A profile to be previewed with
+ */
+ previewFormFields(profile) {
+ log.debug("preview profile in autofillFormFields:", profile);
+ /*
+ for (let fieldDetail of this.fieldDetails) {
+ let value = profile[fieldDetail.fieldName] || "";
+
+ // Skip the fields that already has text entered
+ if (fieldDetail.element.value) {
+ continue;
+ }
+
+ // TODO: Set highlight style and preview text.
+ }
+ */
+ },
+
+ clearPreviewedFormFields() {
+ log.debug("clear previewed fields in:", this.form);
+ /*
+ for (let fieldDetail of this.fieldDetails) {
+ // TODO: Clear preview text
+
+ // We keep the highlight of all fields if this form has
+ // already been auto-filled with a profile.
+ if (this.filledProfileGUID == null) {
+ // TODO: Remove highlight style
+ }
+ }
+ */
+ },
};
--- a/browser/extensions/formautofill/content/FormAutofillFrameScript.js
+++ b/browser/extensions/formautofill/content/FormAutofillFrameScript.js
@@ -3,30 +3,34 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Form Autofill frame script.
*/
"use strict";
+/* global content */
+
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() {
addEventListener("DOMContentLoaded", this);
+ addMessageListener("FormAutofill:PreviewProfile", this);
+ addMessageListener("FormAutoComplete:PopupClosed", this);
},
handleEvent(evt) {
if (!evt.isTrusted) {
return;
}
if (!Services.prefs.getBoolPref("browser.formautofill.enabled")) {
@@ -39,11 +43,24 @@ var FormAutofillFrameScript = {
if (!(doc instanceof Ci.nsIDOMHTMLDocument)) {
return;
}
FormAutofillContent.identifyAutofillFields(doc);
break;
}
}
},
+
+ receiveMessage(aMessage) {
+ if (!Services.prefs.getBoolPref("browser.formautofill.enabled")) {
+ return;
+ }
+
+ switch (aMessage.name) {
+ case "FormAutofill:PreviewProfile":
+ case "FormAutoComplete:PopupClosed":
+ FormAutofillContent._previewProfile(content.document);
+ break;
+ }
+ },
};
FormAutofillFrameScript.init();
--- a/browser/extensions/formautofill/content/formautofill.xml
+++ b/browser/extensions/formautofill/content/formautofill.xml
@@ -38,24 +38,45 @@
this._comment = document.getAnonymousElementByAttribute(
this, "anonid", "profile-comment"
);
this._adjustAcItem();
]]>
</constructor>
+ <property name="selected" onget="return this.getAttribute('selected') == 'true';">
+ <setter><![CDATA[
+ /* global Cu */
+ if (val) {
+ this.setAttribute("selected", "true");
+ } else {
+ this.removeAttribute("selected");
+ }
+
+ let {AutoCompletePopup} = Cu.import("resource://gre/modules/AutoCompletePopup.jsm", {});
+
+ AutoCompletePopup.sendMessageToBrowser("FormAutofill:PreviewProfile");
+
+ return val;
+ ]]></setter>
+ </property>
+
<method name="_cleanup">
<body>
<![CDATA[
this._itemBox.removeAttribute("size");
]]>
</body>
</method>
+ <method name="_onChanged">
+ <body></body>
+ </method>
+
<method name="_onOverflow">
<body></body>
</method>
<method name="_onUnderflow">
<body></body>
</method>