Bug 1658027 - Separate visual interactions on Credit Card Autofill for A/B testing. r=abr, a=jcristau
authorZibi Braniecki <zbraniecki@mozilla.com>
Sat, 08 Aug 2020 19:25:31 +0000
changeset 606758 11c649b8379655560318c6305bb0f803d09a8f69
parent 606757 dc3523dfad0300cb8749b904b31655f748c92c87
child 606759 f1fac0bebca7da575ae6e0273c1a0bda23e024b7
push id13534
push userjcristau@mozilla.com
push dateTue, 11 Aug 2020 13:34:49 +0000
treeherdermozilla-beta@68d145de5fd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersabr, jcristau
bugs1658027
milestone80.0
Bug 1658027 - Separate visual interactions on Credit Card Autofill for A/B testing. r=abr, a=jcristau Differential Revision: https://phabricator.services.mozilla.com/D86445
browser/app/profile/firefox.js
browser/extensions/formautofill/FormAutofill.jsm
browser/extensions/formautofill/FormAutofillContent.jsm
browser/extensions/formautofill/FormAutofillParent.jsm
browser/extensions/formautofill/FormAutofillPreferences.jsm
browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_telemetry.js
browser/extensions/formautofill/test/browser/creditCard/browser_privacyPreferences.js
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1841,16 +1841,19 @@ pref("browser.crashReports.unsubmittedCh
 // The truthy values of "extensions.formautofill.available" are "on" and "detect",
 // any other value means autofill isn't available.
 // "detect" means it's enabled if conditions defined in the extension are met.
 pref("extensions.formautofill.available", "detect");
 pref("extensions.formautofill.creditCards.available", false);
 pref("extensions.formautofill.addresses.enabled", true);
 pref("extensions.formautofill.addresses.capture.enabled", false);
 pref("extensions.formautofill.creditCards.enabled", true);
+// Temporary preference to control displaying the UI elements for
+// credit card autofill used for the duration of the A/B test.
+pref("extensions.formautofill.creditCards.hideui", false);
 // Pref for shield/heartbeat to recognize users who have used Credit Card
 // Autofill. The valid values can be:
 // 0: none
 // 1: submitted a manually-filled credit card form (but didn't see the doorhanger
 //    because of a duplicate profile in the storage)
 // 2: saw the doorhanger
 // 3: submitted an autofill'ed credit card form
 pref("extensions.formautofill.creditCards.used", 0);
--- a/browser/extensions/formautofill/FormAutofill.jsm
+++ b/browser/extensions/formautofill/FormAutofill.jsm
@@ -22,16 +22,18 @@ const CREDITCARDS_USED_STATUS_PREF = "ex
 const ENABLED_AUTOFILL_ADDRESSES_PREF =
   "extensions.formautofill.addresses.enabled";
 const ENABLED_AUTOFILL_ADDRESSES_CAPTURE_PREF =
   "extensions.formautofill.addresses.capture.enabled";
 const ENABLED_AUTOFILL_CREDITCARDS_PREF =
   "extensions.formautofill.creditCards.enabled";
 const ENABLED_AUTOFILL_CREDITCARDS_REAUTH_PREF =
   "extensions.formautofill.reauth.enabled";
+const AUTOFILL_CREDITCARDS_HIDE_UI_PREF =
+  "extensions.formautofill.creditCards.hideui";
 const SUPPORTED_COUNTRIES_PREF = "extensions.formautofill.supportedCountries";
 
 XPCOMUtils.defineLazyPreferenceGetter(
   this,
   "logLevel",
   "extensions.formautofill.loglevel",
   "Warn"
 );
@@ -110,16 +112,21 @@ XPCOMUtils.defineLazyPreferenceGetter(
 );
 XPCOMUtils.defineLazyPreferenceGetter(
   FormAutofill,
   "_isAutofillCreditCardsEnabled",
   ENABLED_AUTOFILL_CREDITCARDS_PREF
 );
 XPCOMUtils.defineLazyPreferenceGetter(
   FormAutofill,
+  "isAutofillCreditCardsHideUI",
+  AUTOFILL_CREDITCARDS_HIDE_UI_PREF
+);
+XPCOMUtils.defineLazyPreferenceGetter(
+  FormAutofill,
   "isAutofillAddressesFirstTimeUse",
   ADDRESSES_FIRST_TIME_USE_PREF
 );
 XPCOMUtils.defineLazyPreferenceGetter(
   FormAutofill,
   "AutofillCreditCardsUsedStatus",
   CREDITCARDS_USED_STATUS_PREF
 );
--- a/browser/extensions/formautofill/FormAutofillContent.jsm
+++ b/browser/extensions/formautofill/FormAutofillContent.jsm
@@ -178,19 +178,23 @@ AutofillProfileAutoCompleteSearch.protot
       activeFieldDetail.fieldName
     );
     const isCreditCardField = FormAutofillUtils.isCreditCardField(
       activeFieldDetail.fieldName
     );
     let isInputAutofilled = activeFieldDetail.state == FIELD_STATES.AUTO_FILLED;
     let allFieldNames = activeSection.allFieldNames;
     let filledRecordGUID = activeSection.filledRecordGUID;
+
+    let creditCardsEnabledAndVisible =
+      FormAutofill.isAutofillCreditCardsEnabled &&
+      !FormAutofill.isAutofillCreditCardsHideUI;
     let searchPermitted = isAddressField
       ? FormAutofill.isAutofillAddressesEnabled
-      : FormAutofill.isAutofillCreditCardsEnabled;
+      : creditCardsEnabledAndVisible;
     let AutocompleteResult = isAddressField ? AddressResult : CreditCardResult;
     let isFormAutofillSearch = true;
     let pendingSearchResult = null;
 
     ProfileAutocomplete.lastProfileAutoCompleteFocusedInput = activeInput;
     // Fallback to form-history if ...
     //   - specified autofill feature is pref off.
     //   - no profile can fill the currently-focused input.
--- a/browser/extensions/formautofill/FormAutofillParent.jsm
+++ b/browser/extensions/formautofill/FormAutofillParent.jsm
@@ -576,16 +576,20 @@ class FormAutofillParent extends JSWindo
           1
         );
       }
     }
     return showDoorhanger;
   }
 
   async _onCreditCardSubmit(creditCard, browser, timeStartedFillingMS) {
+    if (FormAutofill.isAutofillCreditCardsHideUI) {
+      return false;
+    }
+
     // Updates the used status for shield/heartbeat to recognize users who have
     // used Credit Card Autofill.
     let setUsedStatus = status => {
       if (FormAutofill.AutofillCreditCardsUsedStatus < status) {
         Services.prefs.setIntPref(
           FormAutofill.CREDITCARDS_USED_STATUS_PREF,
           status
         );
--- a/browser/extensions/formautofill/FormAutofillPreferences.jsm
+++ b/browser/extensions/formautofill/FormAutofillPreferences.jsm
@@ -171,17 +171,20 @@ FormAutofillPreferences.prototype = {
 
     this.refs = {
       formAutofillFragment,
       formAutofillGroup,
       addressAutofillCheckbox,
       savedAddressesBtn,
     };
 
-    if (FormAutofill.isAutofillCreditCardsAvailable) {
+    if (
+      FormAutofill.isAutofillCreditCardsAvailable &&
+      !FormAutofill.isAutofillCreditCardsHideUI
+    ) {
       let creditCardAutofill = document.createXULElement("hbox");
       let creditCardAutofillCheckboxGroup = document.createXULElement("hbox");
       let creditCardAutofillCheckbox = document.createXULElement("checkbox");
       let creditCardAutofillLearnMore = document.createXULElement("label", {
         is: "text-link",
       });
       let savedCreditCardsBtn = document.createXULElement("button", {
         is: "highlightable-button",
--- a/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_telemetry.js
+++ b/browser/extensions/formautofill/test/browser/creditCard/browser_creditCard_telemetry.js
@@ -586,8 +586,97 @@ add_task(async function test_histogram()
     1: 1,
     2: 2,
   });
 
   await removeAllRecords();
 
   assertHistogram(CC_NUM_USES_HISTOGRAM, {});
 });
+
+add_task(async function test_submit_creditCard_new_with_hidden_ui() {
+  const AUTOFILL_CREDITCARDS_HIDE_UI_PREF =
+    "extensions.formautofill.creditCards.hideui";
+
+  Services.telemetry.clearEvents();
+  Services.telemetry.clearScalars();
+  Services.telemetry.getHistogramById(CC_NUM_USES_HISTOGRAM).clear();
+  Services.telemetry.setEventRecordingEnabled("creditcard", true);
+
+  await SpecialPowers.pushPrefEnv({
+    set: [
+      [CREDITCARDS_USED_STATUS_PREF, 0],
+      [AUTOFILL_CREDITCARDS_HIDE_UI_PREF, true],
+    ],
+  });
+
+  await saveCreditCard(TEST_CREDIT_CARD_1);
+
+  await BrowserTestUtils.withNewTab(
+    { gBrowser, url: CREDITCARD_FORM_URL },
+    async function(browser) {
+      await openPopupOn(browser, "form #cc-number").then(
+        () => {
+          return Promise.reject("Popup should not be displayed");
+        },
+        () => {
+          ok(true, "Popup has not been displayed");
+        }
+      );
+
+      await SpecialPowers.spawn(browser, [], async function() {
+        let form = content.document.getElementById("form");
+        let name = form.querySelector("#cc-name");
+
+        name.focus();
+        name.setUserInput("User 1");
+
+        form.querySelector("#cc-number").setUserInput("5038146897157463");
+        form.querySelector("#cc-exp-month").setUserInput("12");
+        form.querySelector("#cc-exp-year").setUserInput("2017");
+        form.querySelector("#cc-type").value = "mastercard";
+
+        // Wait 1000ms before submission to make sure the input value applied
+        await new Promise(resolve => content.setTimeout(resolve, 1000));
+        form.querySelector("input[type=submit]").click();
+      });
+
+      await sleep(1000);
+      is(PopupNotifications.panel.state, "closed", "Doorhanger is hidden");
+    }
+  );
+
+  SpecialPowers.clearUserPref(CREDITCARDS_USED_STATUS_PREF);
+  SpecialPowers.clearUserPref(ENABLED_AUTOFILL_CREDITCARDS_PREF);
+  SpecialPowers.clearUserPref(AUTOFILL_CREDITCARDS_HIDE_UI_PREF);
+
+  assertHistogram(CC_NUM_USES_HISTOGRAM, { 0: 1 });
+
+  let expected_content = [
+    ["creditcard", "detected", "cc_form"],
+    [
+      "creditcard",
+      "submitted",
+      "cc_form",
+      undefined,
+      {
+        fields_not_auto: "6",
+        fields_auto: "0",
+        fields_modified: "0",
+      },
+    ],
+  ];
+  await assertTelemetry(expected_content, []);
+  await removeAllRecords();
+
+  TelemetryTestUtils.assertScalar(
+    TelemetryTestUtils.getProcessScalars("content"),
+    "formautofill.creditCards.detected_sections_count",
+    1,
+    "There should be 1 sections detected."
+  );
+  TelemetryTestUtils.assertScalar(
+    TelemetryTestUtils.getProcessScalars("content"),
+    "formautofill.creditCards.submitted_sections_count",
+    1,
+    "There should be 1 section submitted."
+  );
+});
--- a/browser/extensions/formautofill/test/browser/creditCard/browser_privacyPreferences.js
+++ b/browser/extensions/formautofill/test/browser/creditCard/browser_privacyPreferences.js
@@ -209,16 +209,47 @@ add_task(async function test_creditCardN
           !content.document.querySelector(selectors.creditCardAutofillCheckbox),
           "Autofill credit cards checkbox should not exist"
         );
       });
     }
   );
 });
 
+add_task(async function test_creditCardHiddenUI() {
+  const AUTOFILL_CREDITCARDS_HIDE_UI_PREF =
+    "extensions.formautofill.creditCards.hideui";
+
+  await SpecialPowers.pushPrefEnv({
+    set: [[AUTOFILL_CREDITCARDS_HIDE_UI_PREF, true]],
+  });
+  let finalPrefPaneLoaded = TestUtils.topicObserved(
+    "sync-pane-loaded",
+    () => true
+  );
+  await BrowserTestUtils.withNewTab(
+    { gBrowser, url: PAGE_PRIVACY },
+    async function(browser) {
+      await finalPrefPaneLoaded;
+      await SpecialPowers.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"
+        );
+      });
+    }
+  );
+  SpecialPowers.clearUserPref(AUTOFILL_CREDITCARDS_HIDE_UI_PREF);
+});
+
 add_task(async function test_reauth() {
   await SpecialPowers.pushPrefEnv({
     set: [[AUTOFILL_CREDITCARDS_AVAILABLE_PREF, true]],
   });
   let { OSKeyStore } = ChromeUtils.import(
     "resource://gre/modules/OSKeyStore.jsm"
   );