Bug 1304306 - (Part 1) Add Form Autofill preference checkbox and button draft
authorScott Wu <scottcwwu@gmail.com>
Thu, 29 Dec 2016 15:54:50 +0800
changeset 481665 e8401e4f616eceed821ee0d3785b513328f14c6b
parent 481595 25a94c1047e793ef096d8556fa3c26dd72bd37d7
child 481666 c37bab6361564c268efd5004ea9e4a7946982582
push id44902
push userbmo:scwwu@mozilla.com
push dateFri, 10 Feb 2017 10:03:56 +0000
bugs1304306
milestone54.0a1
Bug 1304306 - (Part 1) Add Form Autofill preference checkbox and button MozReview-Commit-ID: I7O4l9aQ5JC
browser/app/profile/firefox.js
browser/extensions/formautofill/FormAutofillParent.jsm
browser/extensions/formautofill/FormAutofillPreferences.jsm
browser/extensions/formautofill/locale/en-US/formautofill.properties
browser/extensions/formautofill/locale/jar.mn
browser/extensions/formautofill/locale/moz.build
browser/extensions/formautofill/moz.build
--- 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
@@ -27,21 +27,24 @@
 
 /* exported FormAutofillParent */
 
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "OS",
                                   "resource://gre/modules/osfile.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ProfileStorage",
                                   "resource://formautofill/ProfileStorage.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "FormAutofillPreferences",
+                                  "resource://formautofill/FormAutofillPreferences.jsm");
 
 const PROFILE_JSON_FILE_NAME = "autofill-profiles.json";
 
 let FormAutofillParent = {
   _profileStore: null,
 
   /**
    * Initializes ProfileStorage and registers the message handler.
@@ -52,16 +55,18 @@ let FormAutofillParent = {
 
     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);
+
+    Services.obs.addObserver(this, "advanced-pane-loaded", false);
   },
 
   /**
    * 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.
@@ -72,16 +77,30 @@ let FormAutofillParent = {
         this._populateFieldValues(data, target);
         break;
       case "FormAutofill:GetProfiles":
         this._getProfiles(data, target);
         break;
     }
   },
 
+  observe: function(subject, topic, data) {
+    switch (topic) {
+      case "advanced-pane-loaded": {
+        let formAutofillPreferences = new FormAutofillPreferences();
+        let document = subject.document;
+        let prefGroup = formAutofillPreferences.init(document);
+        let parentNode = document.getElementById("mainPrefPane");
+        let insertBeforeNode = document.getElementById("locationBarGroup");
+        parentNode.insertBefore(prefGroup, insertBeforeNode);
+        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() {
@@ -98,16 +117,18 @@ let FormAutofillParent = {
       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.obs.removeObserver(this, "advanced-pane-loaded");
   },
 
   /**
    * 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
new file mode 100644
--- /dev/null
+++ b/browser/extensions/formautofill/FormAutofillPreferences.jsm
@@ -0,0 +1,137 @@
+/* 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/. */
+
+/**
+ * Creates form autofill preferences group.
+ */
+
+"use strict";
+
+const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+
+const PREF_AUTOFILL_ENABLED = "browser.formautofill.enabled";
+
+function FormAutofillPreferences() {
+  this.bundle = Services.strings.createBundle(
+                  "chrome://formautofill/locale/formautofill.properties");
+}
+
+FormAutofillPreferences.prototype = {
+  /**
+   * Check if Form Autofill feature is enabled.
+   *
+   * @returns {boolean}
+   */
+  get isAutofillEnabled() {
+    return Services.prefs.getBoolPref(PREF_AUTOFILL_ENABLED);
+  },
+
+  /**
+   * Check if the current page is Preferences/Privacy.
+   *
+   * @returns {boolean}
+   */
+  get isPrivacyPane() {
+    return this.refs.document.location.href == "about:preferences#privacy";
+  },
+
+  /**
+   * Create the Form Autofill preference group.
+   *
+   * @param   {XULDocument} document
+   * @returns {XULElement}
+   */
+  init(document) {
+    const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+
+    let formAutofillGroup = document.createElementNS(XUL_NS, "groupbox");
+    let caption = document.createElementNS(XUL_NS, "caption");
+    let captionLabel = document.createElementNS(XUL_NS, "label");
+    let hbox = document.createElementNS(XUL_NS, "hbox");
+    let enabledCheckbox = document.createElementNS(XUL_NS, "checkbox");
+    let spacer = document.createElementNS(XUL_NS, "spacer");
+    let savedProfilesBtn = document.createElementNS(XUL_NS, "button");
+
+    this.refs = {
+      document,
+      formAutofillGroup,
+      enabledCheckbox,
+      savedProfilesBtn,
+    };
+
+    formAutofillGroup.id = "formAutofillGroup";
+    formAutofillGroup.hidden = !this.isPrivacyPane;
+    // Use .setAttribute because HTMLElement.dataset is not available on XUL elements
+    formAutofillGroup.setAttribute("data-category", "panePrivacy");
+
+    captionLabel.textContent = this.bundle.GetStringFromName("preferenceGroupTitle");
+    savedProfilesBtn.setAttribute("label", this.bundle.GetStringFromName("savedProfiles"));
+    enabledCheckbox.setAttribute("label", this.bundle.GetStringFromName("enableProfileAutofill"));
+
+    // Manually set the checked state
+    if (this.isAutofillEnabled) {
+      enabledCheckbox.setAttribute("checked", true);
+    }
+
+    spacer.flex = 1;
+
+    formAutofillGroup.appendChild(caption);
+    caption.appendChild(captionLabel);
+    formAutofillGroup.appendChild(hbox);
+    hbox.appendChild(enabledCheckbox);
+    hbox.appendChild(spacer);
+    hbox.appendChild(savedProfilesBtn);
+
+    this.attachEventListeners();
+
+    return formAutofillGroup;
+  },
+
+  /**
+   * Remove event listeners and the preference group.
+   */
+  uninit() {
+    this.detachEventListeners();
+    this.refs.formAutofillGroup.remove();
+  },
+
+  /**
+   * Handle events
+   *
+   * @param  {DOMEvent} event
+   */
+  handleEvent(event) {
+    switch (event.type) {
+      case "command": {
+        let target = event.target;
+
+        if (target == this.refs.enabledCheckbox) {
+          // Set preference directly instead of relying on <Preference>
+          Services.prefs.setBoolPref(PREF_AUTOFILL_ENABLED, target.checked);
+        } else if (target == this.refs.savedProfilesBtn) {
+          // TODO: Open Saved Profiles dialog
+        }
+        break;
+      }
+    }
+  },
+
+  /**
+   * Attach event listener
+   */
+  attachEventListeners() {
+    this.refs.formAutofillGroup.addEventListener("command", this);
+  },
+
+  /**
+   * Remove event listener
+   */
+  detachEventListeners() {
+    this.refs.formAutofillGroup.removeEventListener("command", this);
+  },
+};
+
+this.EXPORTED_SYMBOLS = ["FormAutofillPreferences"];
new file mode 100644
--- /dev/null
+++ b/browser/extensions/formautofill/locale/en-US/formautofill.properties
@@ -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/.
+
+preferenceGroupTitle = Form Autofill
+enableProfileAutofill = Enable Profile Autofill
+savedProfiles = Saved Profiles…
new file mode 100644
--- /dev/null
+++ b/browser/extensions/formautofill/locale/jar.mn
@@ -0,0 +1,8 @@
+#filter substitution
+# 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/.
+
+@AB_CD@.jar:
+% locale formautofill @AB_CD@ %locale/@AB_CD@/
+  locale/@AB_CD@/                (en-US/*)
new file mode 100644
--- /dev/null
+++ b/browser/extensions/formautofill/locale/moz.build
@@ -0,0 +1,7 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+JAR_MANIFESTS += ['jar.mn']
--- a/browser/extensions/formautofill/moz.build
+++ b/browser/extensions/formautofill/moz.build
@@ -2,16 +2,18 @@
 # vim: set filetype=python:
 # 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/.
 
 DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION']
 DEFINES['MOZ_APP_MAXVERSION'] = CONFIG['MOZ_APP_MAXVERSION']
 
+DIRS += ['locale']
+
 FINAL_TARGET_FILES.features['formautofill@mozilla.org'] += [
   'bootstrap.js'
 ]
 
 FINAL_TARGET_PP_FILES.features['formautofill@mozilla.org'] += [
   'install.rdf.in'
 ]