Bug 1330567 - Part 1: Fallback to form history if form autofill pref is disabled, r?MattN
MozReview-Commit-ID: Aq8NhSkxNId
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1574,14 +1574,15 @@ pref("browser.crashReports.unsubmittedCh
#ifdef NIGHTLY_BUILD
// Enable the (fairly costly) client/server validation on nightly only. The other prefs
// controlling validation are located in /services/sync/services-sync.js
pref("services.sync.validation.enabled", true);
#endif
// Preferences for the form autofill system extension
pref("browser.formautofill.experimental", false);
+pref("browser.formautofill.enabled", false);
// Enable safebrowsing v4 tables (suffixed by "-proto") update.
#ifdef NIGHTLY_BUILD
pref("urlclassifier.malwareTable", "goog-malware-shavar,goog-unwanted-shavar,goog-malware-proto,goog-unwanted-proto,test-malware-simple,test-unwanted-simple");
pref("urlclassifier.phishTable", "goog-phish-shavar,goog-phish-proto,test-phish-simple");
#endif
--- a/browser/extensions/formautofill/FormAutofillParent.jsm
+++ b/browser/extensions/formautofill/FormAutofillParent.jsm
@@ -26,88 +26,140 @@
*/
/* exported FormAutofillParent */
"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");
XPCOMUtils.defineLazyModuleGetter(this, "OS",
"resource://gre/modules/osfile.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ProfileStorage",
"resource://formautofill/ProfileStorage.jsm");
const PROFILE_JSON_FILE_NAME = "autofill-profiles.json";
+const ENABLED_PREF = "browser.formautofill.enabled";
-let FormAutofillParent = {
+function FormAutofillParent() {
+}
+
+FormAutofillParent.prototype = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]),
+
_profileStore: null,
+ _enabled: false,
+
/**
* Initializes ProfileStorage and registers the message handler.
*/
- init: function() {
+ init() {
let storePath =
OS.Path.join(OS.Constants.Path.profileDir, PROFILE_JSON_FILE_NAME);
this._profileStore = new ProfileStorage(storePath);
this._profileStore.initialize();
- let mm = Cc["@mozilla.org/globalmessagemanager;1"]
- .getService(Ci.nsIMessageListenerManager);
- mm.addMessageListener("FormAutofill:PopulateFieldValues", this);
- mm.addMessageListener("FormAutofill:GetProfiles", this);
+ // Observing the pref (and storage) changes
+ Services.prefs.addObserver(ENABLED_PREF, this, false);
+ this._enabled = this._getStatus();
+ // Force to trigger the onStatusChanged function for setting listeners properly
+ // while initizlization
+ this._onStatusChanged();
+ Services.mm.addMessageListener("FormAutofill:getEnabledStatus", this);
+ },
+
+ /**
+ * Observe the pref changes and update _enabled cache if status is changed.
+ */
+ observe() {
+ let currentStatus = this._getStatus();
+
+ if (currentStatus !== this._enabled) {
+ this._enabled = currentStatus;
+ this._onStatusChanged();
+ }
+ },
+
+ /**
+ * Add/remove message listener and broadcast the status to frames while the
+ * form autofill status changed.
+ */
+ _onStatusChanged() {
+ if (this._enabled) {
+ Services.mm.addMessageListener("FormAutofill:PopulateFieldValues", this);
+ Services.mm.addMessageListener("FormAutofill:GetProfiles", this);
+ } else {
+ Services.mm.removeMessageListener("FormAutofill:PopulateFieldValues", this);
+ Services.mm.removeMessageListener("FormAutofill:GetProfiles", this);
+ }
+
+ Services.mm.broadcastAsyncMessage("FormAutofill:enabledStatus", this._enabled);
+ },
+
+ /**
+ * Query pref (and storage) status to determine the overall status for
+ * form autofill feature.
+ *
+ * @returns {boolean} status of form autofill feature
+ */
+ _getStatus() {
+ return Services.prefs.getBoolPref(ENABLED_PREF);
},
/**
* Handles the message coming from FormAutofillContent.
*
* @param {string} message.name The name of the message.
* @param {object} message.data The data of the message.
* @param {nsIFrameMessageManager} message.target Caller's message manager.
*/
- receiveMessage: function({name, data, target}) {
+ receiveMessage({name, data, target}) {
switch (name) {
case "FormAutofill:PopulateFieldValues":
this._populateFieldValues(data, target);
break;
case "FormAutofill:GetProfiles":
this._getProfiles(data, target);
break;
+ case "FormAutofill:getEnabledStatus":
+ target.messageManager.sendAsyncMessage("FormAutofill:enabledStatus",
+ this._enabled);
+ break;
}
},
/**
* Returns the instance of ProfileStorage. To avoid syncing issues, anyone
* who needs to access the profile should request the instance by this instead
* of creating a new one.
*
* @returns {ProfileStorage}
*/
- getProfileStore: function() {
+ getProfileStore() {
return this._profileStore;
},
/**
* Uninitializes FormAutofillParent. This is for testing only.
*
* @private
*/
- _uninit: function() {
+ _uninit() {
if (this._profileStore) {
this._profileStore._saveImmediately();
this._profileStore = null;
}
- let mm = Cc["@mozilla.org/globalmessagemanager;1"]
- .getService(Ci.nsIMessageListenerManager);
- mm.removeMessageListener("FormAutofill:PopulateFieldValues", this);
- mm.removeMessageListener("FormAutofill:GetProfiles", this);
+ Services.mm.removeMessageListener("FormAutofill:PopulateFieldValues", this);
+ Services.mm.removeMessageListener("FormAutofill:GetProfiles", this);
},
/**
* Populates the field values and notifies content to fill in. Exception will
* be thrown if there's no matching profile.
*
* @private
* @param {string} data.guid
--- a/browser/extensions/formautofill/bootstrap.js
+++ b/browser/extensions/formautofill/bootstrap.js
@@ -16,15 +16,16 @@ XPCOMUtils.defineLazyModuleGetter(this,
function startup() {
// Besides this pref, we'll need dom.forms.autocomplete.experimental enabled
// as well to make sure form autocomplete works correctly.
if (!Services.prefs.getBoolPref("browser.formautofill.experimental")) {
return;
}
- FormAutofillParent.init();
+ let parent = new FormAutofillParent();
+ parent.init();
Services.mm.loadFrameScript("chrome://formautofill/content/FormAutofillContent.js", true);
}
function shutdown() {}
function install() {}
function uninstall() {}
--- a/browser/extensions/formautofill/content/FormAutofillContent.js
+++ b/browser/extensions/formautofill/content/FormAutofillContent.js
@@ -335,19 +335,26 @@ let ProfileAutocomplete = {
/**
* Handles content's interactions.
*
* NOTE: Declares it by "var" to make it accessible in unit tests.
*/
var FormAutofillContent = {
init() {
- ProfileAutocomplete.ensureRegistered();
+ addEventListener("DOMContentLoaded", this);
- addEventListener("DOMContentLoaded", this);
+ addMessageListener("FormAutofill:enabledStatus", (result) => {
+ if (result.data) {
+ ProfileAutocomplete.ensureRegistered();
+ } else {
+ ProfileAutocomplete.ensureUnregistered();
+ }
+ });
+ sendAsyncMessage("FormAutofill:getEnabledStatus");
},
handleEvent(evt) {
if (!evt.isTrusted) {
return;
}
switch (evt.type) {
--- a/browser/extensions/formautofill/test/unit/head.js
+++ b/browser/extensions/formautofill/test/unit/head.js
@@ -35,16 +35,18 @@ Components.manager.addBootstrappedManife
// used, on Windows these might still be pending deletion on the physical file
// system. Thus, start from a new base number every time, to make a collision
// with a file that is still pending deletion highly unlikely.
let gFileCounter = Math.floor(Math.random() * 1000000);
function loadFormAutofillContent() {
let facGlobal = {
addEventListener: function() {},
+ addMessageListener: function() {},
+ sendAsyncMessage: function() {},
};
let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Ci.mozIJSSubScriptLoader);
loader.loadSubScriptWithOptions("chrome://formautofill/content/FormAutofillContent.js", {
target: facGlobal,
});
return facGlobal;