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
--- 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"
);