Bug 1399382 - Add a pref to hide credit card autofill feature, r=MattN,lchang draft
authorScott Wu <scottcwwu@gmail.com>
Wed, 13 Sep 2017 18:50:39 +0800
changeset 664789 5a0934c9a87c1368533012a240759df356bb7131
parent 664736 dd6b788f149763c4014c27f2fe1a1d13228bda82
child 731544 89aed73f628dcc148c107c0e492532be7b90665d
push id79804
push userbmo:scwwu@mozilla.com
push dateThu, 14 Sep 2017 11:01:40 +0000
reviewersMattN, lchang
bugs1399382
milestone57.0a1
Bug 1399382 - Add a pref to hide credit card autofill feature, r=MattN,lchang MozReview-Commit-ID: 2GIOrLBmFKR
browser/app/profile/firefox.js
browser/extensions/formautofill/FormAutofillParent.jsm
browser/extensions/formautofill/FormAutofillPreferences.jsm
browser/extensions/formautofill/FormAutofillUtils.jsm
browser/extensions/formautofill/test/browser/browser_privacyPreferences.js
browser/extensions/formautofill/test/browser/head.js
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1695,16 +1695,21 @@ pref("browser.crashReports.unsubmittedCh
 // The value of "extensions.formautofill.available" can be "on", "off" and "detect".
 // The "detect" means it's enabled if conditions defined in the extension are met.
 #ifdef NIGHTLY_BUILD
 pref("extensions.formautofill.available", "on");
 #else
 pref("extensions.formautofill.available", "detect");
 #endif
 pref("extensions.formautofill.addresses.enabled", true);
+#ifdef NIGHTLY_BUILD
+pref("extensions.formautofill.creditCards.available", true);
+#else
+pref("extensions.formautofill.creditCards.available", false);
+#endif
 pref("extensions.formautofill.creditCards.enabled", true);
 pref("extensions.formautofill.firstTimeUse", true);
 pref("extensions.formautofill.heuristics.enabled", true);
 pref("extensions.formautofill.loglevel", "Warn");
 
 // Whether or not to restore a session with lazy-browser tabs.
 pref("browser.sessionstore.restore_tabs_lazily", true);
 
--- a/browser/extensions/formautofill/FormAutofillParent.jsm
+++ b/browser/extensions/formautofill/FormAutofillParent.jsm
@@ -83,27 +83,31 @@ FormAutofillParent.prototype = {
   /**
    * Initializes ProfileStorage and registers the message handler.
    */
   async init() {
     Services.obs.addObserver(this, "sync-pane-loaded");
     Services.ppmm.addMessageListener("FormAutofill:InitStorage", this);
     Services.ppmm.addMessageListener("FormAutofill:GetRecords", this);
     Services.ppmm.addMessageListener("FormAutofill:SaveAddress", this);
-    Services.ppmm.addMessageListener("FormAutofill:SaveCreditCard", this);
     Services.ppmm.addMessageListener("FormAutofill:RemoveAddresses", this);
-    Services.ppmm.addMessageListener("FormAutofill:RemoveCreditCards", this);
     Services.ppmm.addMessageListener("FormAutofill:OpenPreferences", this);
-    Services.ppmm.addMessageListener("FormAutofill:GetDecryptedString", this);
     Services.mm.addMessageListener("FormAutofill:OnFormSubmit", this);
 
     // Observing the pref and storage changes
     Services.prefs.addObserver(ENABLED_AUTOFILL_ADDRESSES_PREF, this);
-    Services.prefs.addObserver(ENABLED_AUTOFILL_CREDITCARDS_PREF, this);
     Services.obs.addObserver(this, "formautofill-storage-changed");
+
+    // Only listen to credit card related messages if it is available
+    if (FormAutofillUtils.isAutofillCreditCardsAvailable) {
+      Services.ppmm.addMessageListener("FormAutofill:SaveCreditCard", this);
+      Services.ppmm.addMessageListener("FormAutofill:RemoveCreditCards", this);
+      Services.ppmm.addMessageListener("FormAutofill:GetDecryptedString", this);
+      Services.prefs.addObserver(ENABLED_AUTOFILL_CREDITCARDS_PREF, this);
+    }
   },
 
   observe(subject, topic, data) {
     log.debug("observe:", topic, "with data:", data);
     switch (topic) {
       case "sync-pane-loaded": {
         let formAutofillPreferences = new FormAutofillPreferences();
         let document = subject.document;
@@ -243,22 +247,26 @@ FormAutofillParent.prototype = {
    * @private
    */
   _uninit() {
     this.profileStorage._saveImmediately();
 
     Services.ppmm.removeMessageListener("FormAutofill:InitStorage", this);
     Services.ppmm.removeMessageListener("FormAutofill:GetRecords", this);
     Services.ppmm.removeMessageListener("FormAutofill:SaveAddress", this);
-    Services.ppmm.removeMessageListener("FormAutofill:SaveCreditCard", this);
     Services.ppmm.removeMessageListener("FormAutofill:RemoveAddresses", this);
-    Services.ppmm.removeMessageListener("FormAutofill:RemoveCreditCards", this);
     Services.obs.removeObserver(this, "sync-pane-loaded");
     Services.prefs.removeObserver(ENABLED_AUTOFILL_ADDRESSES_PREF, this);
-    Services.prefs.removeObserver(ENABLED_AUTOFILL_CREDITCARDS_PREF, this);
+
+    if (FormAutofillUtils.isAutofillCreditCardsAvailable) {
+      Services.ppmm.removeMessageListener("FormAutofill:SaveCreditCard", this);
+      Services.ppmm.removeMessageListener("FormAutofill:RemoveCreditCards", this);
+      Services.ppmm.removeMessageListener("FormAutofill:GetDecryptedString", this);
+      Services.prefs.removeObserver(ENABLED_AUTOFILL_CREDITCARDS_PREF, this);
+    }
   },
 
   /**
    * Get the records from profile store and return results back to content
    * process. It will decrypt the credit card number and append
    * "cc-number-decrypted" to each record if MasterPassword isn't set.
    *
    * @private
--- a/browser/extensions/formautofill/FormAutofillPreferences.jsm
+++ b/browser/extensions/formautofill/FormAutofillPreferences.jsm
@@ -56,79 +56,89 @@ FormAutofillPreferences.prototype = {
   },
 
   /**
    * Create Form Autofill preference group
    *
    * @param  {XULDocument} document
    */
   createPreferenceGroup(document) {
+    let learnMoreURL = Services.urlFormatter.formatURLPref("app.support.baseURL") + "autofill-card-address";
     let formAutofillGroup = document.createElementNS(XUL_NS, "vbox");
     let addressAutofill = document.createElementNS(XUL_NS, "hbox");
     let addressAutofillCheckboxGroup = document.createElementNS(XUL_NS, "description");
     let addressAutofillCheckbox = document.createElementNS(XUL_NS, "checkbox");
     let addressAutofillLearnMore = document.createElementNS(XUL_NS, "label");
     let savedAddressesBtn = document.createElementNS(XUL_NS, "button");
-    let creditCardAutofill = document.createElementNS(XUL_NS, "hbox");
-    let creditCardAutofillCheckboxGroup = document.createElementNS(XUL_NS, "description");
-    let creditCardAutofillCheckbox = document.createElementNS(XUL_NS, "checkbox");
-    let creditCardAutofillLearnMore = document.createElementNS(XUL_NS, "label");
-    let savedCreditCardsBtn = document.createElementNS(XUL_NS, "button");
-
     savedAddressesBtn.className = "accessory-button";
-    savedCreditCardsBtn.className = "accessory-button";
     addressAutofillLearnMore.className = "learnMore text-link";
-    creditCardAutofillLearnMore.className = "learnMore text-link";
-
-    this.refs = {
-      formAutofillGroup,
-      addressAutofillCheckbox,
-      savedAddressesBtn,
-      creditCardAutofillCheckbox,
-      savedCreditCardsBtn,
-    };
 
     formAutofillGroup.id = "formAutofillGroup";
     addressAutofill.id = "addressAutofill";
     addressAutofillLearnMore.id = "addressAutofillLearnMore";
-    creditCardAutofill.id = "creditCardAutofill";
-    creditCardAutofillLearnMore.id = "creditCardAutofillLearnMore";
 
     addressAutofillLearnMore.setAttribute("value", this.bundle.GetStringFromName("learnMore"));
     addressAutofillCheckbox.setAttribute("label", this.bundle.GetStringFromName("enableAddressAutofill"));
     savedAddressesBtn.setAttribute("label", this.bundle.GetStringFromName("savedAddresses"));
-    creditCardAutofillLearnMore.setAttribute("value", this.bundle.GetStringFromName("learnMore"));
-    creditCardAutofillCheckbox.setAttribute("label", this.bundle.GetStringFromName("enableCreditCardAutofill"));
-    savedCreditCardsBtn.setAttribute("label", this.bundle.GetStringFromName("savedCreditCards"));
 
-    let learnMoreURL = Services.urlFormatter.formatURLPref("app.support.baseURL") + "autofill-card-address";
     addressAutofillLearnMore.setAttribute("href", learnMoreURL);
-    creditCardAutofillLearnMore.setAttribute("href", learnMoreURL);
 
     // Manually set the checked state
     if (FormAutofillUtils.isAutofillAddressesEnabled) {
       addressAutofillCheckbox.setAttribute("checked", true);
     }
-    if (FormAutofillUtils.isAutofillCreditCardsEnabled) {
-      creditCardAutofillCheckbox.setAttribute("checked", true);
-    }
 
     addressAutofillCheckboxGroup.flex = 1;
-    creditCardAutofillCheckboxGroup.flex = 1;
 
     formAutofillGroup.appendChild(addressAutofill);
     addressAutofill.appendChild(addressAutofillCheckboxGroup);
     addressAutofillCheckboxGroup.appendChild(addressAutofillCheckbox);
     addressAutofillCheckboxGroup.appendChild(addressAutofillLearnMore);
     addressAutofill.appendChild(savedAddressesBtn);
-    formAutofillGroup.appendChild(creditCardAutofill);
-    creditCardAutofill.appendChild(creditCardAutofillCheckboxGroup);
-    creditCardAutofillCheckboxGroup.appendChild(creditCardAutofillCheckbox);
-    creditCardAutofillCheckboxGroup.appendChild(creditCardAutofillLearnMore);
-    creditCardAutofill.appendChild(savedCreditCardsBtn);
+
+    this.refs = {
+      formAutofillGroup,
+      addressAutofillCheckbox,
+      savedAddressesBtn,
+    };
+
+    if (FormAutofillUtils.isAutofillCreditCardsAvailable) {
+      let creditCardAutofill = document.createElementNS(XUL_NS, "hbox");
+      let creditCardAutofillCheckboxGroup = document.createElementNS(XUL_NS, "description");
+      let creditCardAutofillCheckbox = document.createElementNS(XUL_NS, "checkbox");
+      let creditCardAutofillLearnMore = document.createElementNS(XUL_NS, "label");
+      let savedCreditCardsBtn = document.createElementNS(XUL_NS, "button");
+      savedCreditCardsBtn.className = "accessory-button";
+      creditCardAutofillLearnMore.className = "learnMore text-link";
+
+      creditCardAutofill.id = "creditCardAutofill";
+      creditCardAutofillLearnMore.id = "creditCardAutofillLearnMore";
+
+      creditCardAutofillLearnMore.setAttribute("value", this.bundle.GetStringFromName("learnMore"));
+      creditCardAutofillCheckbox.setAttribute("label", this.bundle.GetStringFromName("enableCreditCardAutofill"));
+      savedCreditCardsBtn.setAttribute("label", this.bundle.GetStringFromName("savedCreditCards"));
+
+      creditCardAutofillLearnMore.setAttribute("href", learnMoreURL);
+
+      // Manually set the checked state
+      if (FormAutofillUtils.isAutofillCreditCardsEnabled) {
+        creditCardAutofillCheckbox.setAttribute("checked", true);
+      }
+
+      creditCardAutofillCheckboxGroup.flex = 1;
+
+      formAutofillGroup.appendChild(creditCardAutofill);
+      creditCardAutofill.appendChild(creditCardAutofillCheckboxGroup);
+      creditCardAutofillCheckboxGroup.appendChild(creditCardAutofillCheckbox);
+      creditCardAutofillCheckboxGroup.appendChild(creditCardAutofillLearnMore);
+      creditCardAutofill.appendChild(savedCreditCardsBtn);
+
+      this.refs.creditCardAutofillCheckbox = creditCardAutofillCheckbox;
+      this.refs.savedCreditCardsBtn = savedCreditCardsBtn;
+    }
   },
 
   /**
    * Handle events
    *
    * @param  {DOMEvent} event
    */
   handleEvent(event) {
--- a/browser/extensions/formautofill/FormAutofillUtils.jsm
+++ b/browser/extensions/formautofill/FormAutofillUtils.jsm
@@ -14,24 +14,26 @@ const ADDRESS_REFERENCES = "chrome://for
 //       bug 1370193.
 const ALTERNATIVE_COUNTRY_NAMES = {
   "US": ["US", "United States of America", "United States", "America", "U.S.", "USA", "U.S.A.", "U.S.A"],
 };
 
 const ADDRESSES_COLLECTION_NAME = "addresses";
 const CREDITCARDS_COLLECTION_NAME = "creditCards";
 const ENABLED_AUTOFILL_ADDRESSES_PREF = "extensions.formautofill.addresses.enabled";
+const AUTOFILL_CREDITCARDS_AVAILABLE_PREF = "extensions.formautofill.creditCards.available";
 const ENABLED_AUTOFILL_CREDITCARDS_PREF = "extensions.formautofill.creditCards.enabled";
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 this.FormAutofillUtils = {
   get AUTOFILL_FIELDS_THRESHOLD() { return 3; },
   get isAutofillEnabled() { return this.isAutofillAddressesEnabled || this.isAutofillCreditCardsEnabled; },
+  get isAutofillCreditCardsEnabled() { return this.isAutofillCreditCardsAvailable && this._isAutofillCreditCardsEnabled; },
 
   ADDRESSES_COLLECTION_NAME,
   CREDITCARDS_COLLECTION_NAME,
   ENABLED_AUTOFILL_ADDRESSES_PREF,
   ENABLED_AUTOFILL_CREDITCARDS_PREF,
 
   _fieldNameInfo: {
     "name": "name",
@@ -521,9 +523,11 @@ this.FormAutofillUtils.defineLazyLogGett
 
 XPCOMUtils.defineLazyGetter(FormAutofillUtils, "stringBundle", function() {
   return Services.strings.createBundle("chrome://formautofill/locale/formautofill.properties");
 });
 
 XPCOMUtils.defineLazyPreferenceGetter(this.FormAutofillUtils,
                                       "isAutofillAddressesEnabled", ENABLED_AUTOFILL_ADDRESSES_PREF);
 XPCOMUtils.defineLazyPreferenceGetter(this.FormAutofillUtils,
-                                      "isAutofillCreditCardsEnabled", ENABLED_AUTOFILL_CREDITCARDS_PREF);
+                                      "isAutofillCreditCardsAvailable", AUTOFILL_CREDITCARDS_AVAILABLE_PREF);
+XPCOMUtils.defineLazyPreferenceGetter(this.FormAutofillUtils,
+                                      "_isAutofillCreditCardsEnabled", ENABLED_AUTOFILL_CREDITCARDS_PREF);
--- a/browser/extensions/formautofill/test/browser/browser_privacyPreferences.js
+++ b/browser/extensions/formautofill/test/browser/browser_privacyPreferences.js
@@ -78,8 +78,22 @@ add_task(async function test_autofillDis
         "Form Autofill group should be visible");
       is(content.document.querySelector(selectors.addressAutofillCheckbox).checked, false,
         "Checkbox should be unchecked when Autofill Addresses is disabled");
       is(content.document.querySelector(selectors.creditCardAutofillCheckbox).checked, false,
         "Checkbox should be unchecked when Autofill Credit Cards is disabled");
     });
   });
 });
+
+add_task(async function test_creditCardNotAvailable() {
+  SpecialPowers.pushPrefEnv({set: [[AUTOFILL_CREDITCARDS_AVAILABLE_PREF, false]]});
+  let finalPrefPaneLoaded = TestUtils.topicObserved("sync-pane-loaded", () => true);
+  await BrowserTestUtils.withNewTab({gBrowser, url: PAGE_PRIVACY}, async function(browser) {
+    await finalPrefPaneLoaded;
+    await ContentTask.spawn(browser, SELECTORS, (selectors) => {
+      is(content.document.querySelector(selectors.group).hidden, false,
+        "Form Autofill group should be visible");
+      ok(!content.document.querySelector(selectors.creditCardAutofillCheckbox),
+        "Autofill credit cards checkbox should not exist");
+    });
+  });
+});
--- a/browser/extensions/formautofill/test/browser/head.js
+++ b/browser/extensions/formautofill/test/browser/head.js
@@ -1,28 +1,30 @@
 /* exported MANAGE_ADDRESSES_DIALOG_URL, MANAGE_CREDIT_CARDS_DIALOG_URL, EDIT_ADDRESS_DIALOG_URL, EDIT_CREDIT_CARD_DIALOG_URL,
             BASE_URL, TEST_ADDRESS_1, TEST_ADDRESS_2, TEST_ADDRESS_3, TEST_ADDRESS_4, TEST_ADDRESS_5,
             TEST_CREDIT_CARD_1, TEST_CREDIT_CARD_2, TEST_CREDIT_CARD_3, FORM_URL, CREDITCARD_FORM_URL,
-            FTU_PREF, ENABLED_AUTOFILL_ADDRESSES_PREF, ENABLED_AUTOFILL_CREDITCARDS_PREF, SYNC_USERNAME_PREF, SYNC_ADDRESSES_PREF,
+            FTU_PREF, ENABLED_AUTOFILL_ADDRESSES_PREF, AUTOFILL_CREDITCARDS_AVAILABLE_PREF, ENABLED_AUTOFILL_CREDITCARDS_PREF,
+            SYNC_USERNAME_PREF, SYNC_ADDRESSES_PREF,
             sleep, expectPopupOpen, openPopupOn, expectPopupClose, closePopup, clickDoorhangerButton,
             getAddresses, saveAddress, removeAddresses, saveCreditCard,
             getDisplayedPopupItems, getDoorhangerCheckbox, waitForMasterPasswordDialog */
 
 "use strict";
 
 const MANAGE_ADDRESSES_DIALOG_URL = "chrome://formautofill/content/manageAddresses.xhtml";
 const MANAGE_CREDIT_CARDS_DIALOG_URL = "chrome://formautofill/content/manageCreditCards.xhtml";
 const EDIT_ADDRESS_DIALOG_URL = "chrome://formautofill/content/editAddress.xhtml";
 const EDIT_CREDIT_CARD_DIALOG_URL = "chrome://formautofill/content/editCreditCard.xhtml";
 const BASE_URL = "http://mochi.test:8888/browser/browser/extensions/formautofill/test/browser/";
 const FORM_URL = "http://mochi.test:8888/browser/browser/extensions/formautofill/test/browser/autocomplete_basic.html";
 const CREDITCARD_FORM_URL =
   "http://mochi.test:8888/browser/browser/extensions/formautofill/test/browser/autocomplete_creditcard_basic.html";
 const FTU_PREF = "extensions.formautofill.firstTimeUse";
 const ENABLED_AUTOFILL_ADDRESSES_PREF = "extensions.formautofill.addresses.enabled";
+const AUTOFILL_CREDITCARDS_AVAILABLE_PREF = "extensions.formautofill.creditCards.available";
 const ENABLED_AUTOFILL_CREDITCARDS_PREF = "extensions.formautofill.creditCards.enabled";
 const SYNC_USERNAME_PREF = "services.sync.username";
 const SYNC_ADDRESSES_PREF = "services.sync.engine.addresses";
 
 const TEST_ADDRESS_1 = {
   "given-name": "John",
   "additional-name": "R.",
   "family-name": "Smith",