Bug 1658027 - Separate visual interactions on Credit Card Autofill for A/B testing. r=abr
authorZibi Braniecki <zbraniecki@mozilla.com>
Sat, 08 Aug 2020 19:25:31 +0000
changeset 544033 1cf57f1b0ed0cc2c6fcbdd0f421b4ea1131430e5
parent 544032 b579c12907dc3bb210177454a696ccc181c1ded0
child 544034 6c39cafd999e0eae6ebd0b79e4494b8c9c42f654
push id123765
push userzbraniecki@mozilla.com
push dateSat, 08 Aug 2020 19:28:15 +0000
treeherderautoland@1cf57f1b0ed0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersabr
bugs1658027
milestone81.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1658027 - Separate visual interactions on Credit Card Autofill for A/B testing. r=abr 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
@@ -1844,16 +1844,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", true);
 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);
 // Enable the checkbox in sync options for credit card data sync service
 pref("services.sync.engine.creditcards.available", true);
 // 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
--- 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"
   );