Bug 1745248 - Allow each autofill feature to detect if it should be enabled depending on search region. r=dimi,sgalich,preferences-reviewers,skhamis,LougeniaBailey

Differential Revision: https://phabricator.services.mozilla.com/D133818
This commit is contained in:
Tim Giles 2022-02-08 19:31:58 +00:00
parent 875c819715
commit 7d4695982b
12 changed files with 364 additions and 86 deletions

View File

@ -25,9 +25,17 @@ add_task(async function test_openPreferences_spotlight() {
]) {
if (
arg == "privacy-credit-card-autofill" &&
!Services.prefs.getBoolPref(
"extensions.formautofill.creditCards.available"
)
Services.prefs.getCharPref(
"extensions.formautofill.creditCards.supported"
) == "off"
) {
continue;
}
if (
arg == "privacy-address-autofill" &&
Services.prefs.getCharPref(
"extensions.formautofill.addresses.supported"
) == "off"
) {
continue;
}

View File

@ -72,29 +72,62 @@ function ensureCssLoaded(domWindow) {
);
}
function isAvailable() {
let availablePref = Services.prefs.getCharPref(
"extensions.formautofill.available"
);
if (availablePref == "on") {
return true;
} else if (availablePref == "detect") {
let region = Services.prefs.getCharPref("browser.search.region", "");
let supportedCountries = Services.prefs
.getCharPref("extensions.formautofill.supportedCountries")
.split(",");
if (
!Services.prefs.getBoolPref("extensions.formautofill.supportRTL") &&
Services.locale.isAppLocaleRTL
) {
return false;
}
return supportedCountries.includes(region);
}
return false;
}
this.formautofill = class extends ExtensionAPI {
/**
* Adjusts and checks form autofill preferences during startup.
*
* @param {boolean} addressAutofillAvailable
* @param {boolean} creditCardAutofillAvailable
*/
adjustAndCheckFormAutofillPrefs(
addressAutofillAvailable,
creditCardAutofillAvailable
) {
// Reset the sync prefs in case the features were previously available
// but aren't now.
if (!creditCardAutofillAvailable) {
Services.prefs.clearUserPref(
"services.sync.engine.creditcards.available"
);
}
if (!addressAutofillAvailable) {
Services.prefs.clearUserPref("services.sync.engine.addresses.available");
}
if (!addressAutofillAvailable && !creditCardAutofillAvailable) {
Services.prefs.clearUserPref("dom.forms.autocomplete.formautofill");
Services.telemetry.scalarSet("formautofill.availability", false);
return;
}
// This pref is used for web contents to detect the autocomplete feature.
// When it's true, "element.autocomplete" will return tokens we currently
// support -- otherwise it'll return an empty string.
Services.prefs.setBoolPref("dom.forms.autocomplete.formautofill", true);
Services.telemetry.scalarSet("formautofill.availability", true);
// These "*.available" prefs determines whether the "addresses"/"creditcards" sync engine is
// available (ie, whether it is shown in any UI etc) - it *does not* determine
// whether the engine is actually enabled or not.
if (FormAutofill.isAutofillAddressesAvailable) {
Services.prefs.setBoolPref(
"services.sync.engine.addresses.available",
true
);
} else {
Services.prefs.clearUserPref("services.sync.engine.addresses.available");
}
if (FormAutofill.isAutofillCreditCardsAvailable) {
Services.prefs.setBoolPref(
"services.sync.engine.creditcards.available",
true
);
} else {
Services.prefs.clearUserPref(
"services.sync.engine.creditcards.available"
);
}
}
onStartup() {
// We have to do this before actually determining if we're enabled, since
// there are scripts inside of the core browser code that depend on the
@ -132,43 +165,16 @@ this.formautofill = class extends ExtensionAPI {
"Cannot find formautofill chrome.manifest for registring translated strings"
);
}
if (!isAvailable()) {
Services.prefs.clearUserPref("dom.forms.autocomplete.formautofill");
// reset the sync related prefs incase the feature was previously available
// but isn't now.
Services.prefs.clearUserPref("services.sync.engine.addresses.available");
Services.prefs.clearUserPref(
"services.sync.engine.creditcards.available"
);
Services.telemetry.scalarSet("formautofill.availability", false);
let addressAutofillAvailable = FormAutofill.isAutofillAddressesAvailable;
let creditCardAutofillAvailable =
FormAutofill.isAutofillCreditCardsAvailable;
this.adjustAndCheckFormAutofillPrefs(
addressAutofillAvailable,
creditCardAutofillAvailable
);
if (!creditCardAutofillAvailable && !addressAutofillAvailable) {
return;
}
// This pref is used for web contents to detect the autocomplete feature.
// When it's true, "element.autocomplete" will return tokens we currently
// support -- otherwise it'll return an empty string.
Services.prefs.setBoolPref("dom.forms.autocomplete.formautofill", true);
Services.telemetry.scalarSet("formautofill.availability", true);
// This pref determines whether the "addresses"/"creditcards" sync engine is
// available (ie, whether it is shown in any UI etc) - it *does not* determine
// whether the engine is actually enabled or not.
Services.prefs.setBoolPref(
"services.sync.engine.addresses.available",
true
);
if (FormAutofill.isAutofillCreditCardsAvailable) {
Services.prefs.setBoolPref(
"services.sync.engine.creditcards.available",
true
);
} else {
Services.prefs.clearUserPref(
"services.sync.engine.creditcards.available"
);
}
// Listen for the autocomplete popup message
// or the form submitted message (which may trigger a
// doorhanger) to lazily append our stylesheets related

View File

@ -1,6 +1,6 @@
[DEFAULT]
prefs =
extensions.formautofill.creditCards.available=true
extensions.formautofill.creditCards.supported=on
extensions.formautofill.creditCards.enabled=true
extensions.formautofill.reauth.enabled=true
support-files =

View File

@ -1,4 +1,9 @@
[DEFAULT]
prefs =
extensions.formautofill.creditCards.new.available=on
extensions.formautofill.creditCards.enabled=true
extensions.formautofill.addresses.availability=on
extensions.formautofill.addresses.enabled=true
skip-if = toolkit == 'android' # bug 1730213
support-files =
../../../../../toolkit/components/satchel/test/satchel_common.js
@ -12,7 +17,9 @@ support-files =
[test_basic_autocomplete_form.html]
[test_form_changes.html]
[test_formautofill_preview_highlight.html]
skip-if = verify || (!debug && os == "mac") # perma-fail see Bug 1600059
skip-if =
verify
(!debug && os == "mac") # perma-fail see Bug 1600059
[test_multi_locale_CA_address_form.html]
[test_multiple_forms.html]
[test_on_address_submission.html]

View File

@ -314,13 +314,28 @@ add_task(async function head_initialize() {
Services.prefs.setBoolPref("extensions.formautofill.section.enabled", true);
Services.prefs.setBoolPref("dom.forms.autocomplete.formautofill", true);
Services.prefs.setCharPref(
"extensions.formautofill.addresses.supported",
"on"
);
Services.prefs.setCharPref(
"extensions.formautofill.creditCards.supported",
"on"
);
Services.prefs.setBoolPref("extensions.formautofill.addresses.enabled", true);
Services.prefs.setBoolPref(
"extensions.formautofill.creditCards.enabled",
true
);
// Clean up after every test.
registerCleanupFunction(function head_cleanup() {
Services.prefs.clearUserPref("extensions.formautofill.available");
Services.prefs.clearUserPref("extensions.experiments.enabled");
Services.prefs.clearUserPref(
"extensions.formautofill.creditCards.available"
"extensions.formautofill.creditCards.supported"
);
Services.prefs.clearUserPref("extensions.formautofill.addresses.supported");
Services.prefs.clearUserPref("extensions.formautofill.creditCards.enabled");
Services.prefs.clearUserPref("extensions.formautofill.heuristics.enabled");
Services.prefs.clearUserPref("extensions.formautofill.section.enabled");

View File

@ -864,9 +864,9 @@ add_task(async function test_creditCardFillDisabled() {
});
add_task(async function test_creditCardFillUnavailable() {
Services.prefs.setBoolPref(
"extensions.formautofill.creditCards.available",
false
Services.prefs.setCharPref(
"extensions.formautofill.creditCards.supported",
"off"
);
let path = getTempFile(TEST_STORE_FILE_NAME).path;
@ -883,9 +883,4 @@ add_task(async function test_creditCardFillUnavailable() {
"Please restart if you flip the pref manually."
);
}
Services.prefs.setBoolPref(
"extensions.formautofill.creditCards.available",
true
);
});

View File

@ -0,0 +1,74 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test enabling address autofill in specific locales and regions.
*/
"use strict";
const { FormAutofill } = ChromeUtils.import(
"resource://autofill/FormAutofill.jsm"
);
add_task(async function test_defaultTestEnvironment() {
Assert.equal(
Services.prefs.getCharPref("extensions.formautofill.addressess.supported"),
"on"
);
});
add_task(async function test_default_supported_module_and_autofill_region() {
Services.prefs.setCharPref("browser.search.region", "US");
registerCleanupFunction(function cleanupRegion() {
Services.prefs.clearUserPref("browser.search.region");
});
let addon = await AddonManager.getAddonByID(EXTENSION_ID);
await addon.reload();
Assert.equal(FormAutofill.isAutofillAddressesAvailable, true);
Assert.equal(FormAutofill.isAutofillAddressesEnabled, true);
});
add_task(
async function test_supported_creditCard_region_unsupported_address_region() {
Services.prefs.setCharPref(
"extensions.formautofill.addressess.supported",
"detect"
);
Services.prefs.setCharPref(
"extensions.formautofill.creditCards.supported",
"detect"
);
Services.prefs.setCharPref("browser.search.region", "FR");
Services.prefs.setCharPref(
"extensions.formautofill.addresses.supportedCountries",
"US,CA"
);
Services.prefs.setCharPref(
"extensions.formautofill.creditCards.supportedCountries",
"US,CA,FR"
);
registerCleanupFunction(function cleanupPrefs() {
Services.prefs.clearUserPref("browser.search.region");
Services.prefs.clearUserPref(
"extensions.formautofill.addresses.supportedCountries"
);
Services.prefs.clearUserPref(
"extensions.formautofill.addressess.supported"
);
Services.prefs.clearUserPref(
"extensions.formautofill.creditCards.supported"
);
});
let addon = await AddonManager.getAddonByID(EXTENSION_ID);
await addon.reload();
Assert.ok(
Services.prefs.getBoolPref("extensions.formautofill.creditCards.enabled")
);
Assert.equal(FormAutofill.isAutofillAddressesAvailable, false);
Assert.equal(FormAutofill.isAutofillAddressesEnabled, false);
}
);

View File

@ -0,0 +1,82 @@
/**
* Test enabling the feature in specific locales and regions.
*/
"use strict";
const { FormAutofill } = ChromeUtils.import(
"resource://autofill/FormAutofill.jsm"
);
add_task(async function test_defaultTestEnvironment() {
Assert.ok(Services.prefs.getBoolPref("dom.forms.autocomplete.formautofill"));
});
add_task(async function test_detect_unsupportedRegion() {
Services.prefs.setCharPref(
"extensions.formautofill.creditCards.supported",
"detect"
);
Services.prefs.setCharPref(
"extensions.formautofill.creditCards.supportedCountries",
"US,CA"
);
Services.prefs.setCharPref("browser.search.region", "ZZ");
registerCleanupFunction(function cleanupRegion() {
Services.prefs.clearUserPref("browser.search.region");
Services.prefs.clearUserPref(
"extensions.formautofill.creditCards.supported"
);
Services.prefs.clearUserPref("extensions.formautofill.addresses.supported");
Services.prefs.clearUserPref(
"extensions.formautofill.creditCards.supportedCountries"
);
});
let addon = await AddonManager.getAddonByID(EXTENSION_ID);
await addon.reload();
Assert.equal(
FormAutofill.isAutofillCreditCardsAvailable,
false,
"Credit card autofill should not be available"
);
Assert.equal(
FormAutofill.isAutofillCreditCardsEnabled,
false,
"Credit card autofill should not be enabled"
);
});
add_task(async function test_detect_supportedRegion() {
Services.prefs.setCharPref(
"extensions.formautofill.creditCards.supported",
"detect"
);
Services.prefs.setCharPref(
"extensions.formautofill.creditCards.supportedCountries",
"US,CA"
);
Services.prefs.setCharPref("browser.search.region", "US");
registerCleanupFunction(function cleanupRegion() {
Services.prefs.clearUserPref("browser.search.region");
Services.prefs.clearUserPref(
"extensions.formautofill.creditCards.supported"
);
Services.prefs.clearUserPref(
"extensions.formautofill.creditCards.supportedCountries"
);
});
let addon = await AddonManager.getAddonByID(EXTENSION_ID);
await addon.reload();
Assert.equal(
FormAutofill.isAutofillCreditCardsAvailable,
true,
"Credit card autofill should be available"
);
Assert.equal(
FormAutofill.isAutofillCreditCardsEnabled,
true,
"Credit card autofill should be enabled"
);
});

View File

@ -4587,14 +4587,22 @@ pref("browser.privatebrowsing.autostart", false);
pref("security.external_protocol_requires_permission", true);
// Preferences for the form autofill toolkit component.
// The truthy values of "extensions.formautofill.available" are "on" and "detect",
// The truthy values of "extensions.formautofill.addresses.available"
// and "extensions.formautofill.creditCards.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.
// Note: "extensions.formautofill.available" and "extensions.formautofill.creditCards.available"
// are not being used in form autofill, but need to exist for migration purposes.
pref("extensions.formautofill.available", "detect");
pref("extensions.formautofill.addresses.supported", "detect");
pref("extensions.formautofill.addresses.enabled", true);
pref("extensions.formautofill.addresses.capture.enabled", false);
pref("extensions.formautofill.addresses.supportedCountries", "US,CA");
// Note: this ".available" pref is only used for migration purposes and will be removed/replaced later.
pref("extensions.formautofill.creditCards.available", true);
pref("extensions.formautofill.creditCards.supported", "detect");
pref("extensions.formautofill.creditCards.enabled", true);
pref("extensions.formautofill.creditCards.supportedCountries", "US,CA");
// 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);
@ -4613,5 +4621,4 @@ pref("extensions.formautofill.loglevel", "Warn");
pref("toolkit.osKeyStore.loglevel", "Warn");
pref("extensions.formautofill.supportedCountries", "US,CA");
pref("extensions.formautofill.supportRTL", false);

View File

@ -16,20 +16,28 @@ XPCOMUtils.defineLazyModuleGetters(this, {
});
const ADDRESSES_FIRST_TIME_USE_PREF = "extensions.formautofill.firstTimeUse";
const AUTOFILL_ADDRESSES_AVAILABLE_PREF =
"extensions.formautofill.addresses.supported";
// This pref should be refactored after the migration of the old bool pref
const AUTOFILL_CREDITCARDS_AVAILABLE_PREF =
"extensions.formautofill.creditCards.available";
"extensions.formautofill.creditCards.supported";
const BROWSER_SEARCH_REGION_PREF = "browser.search.region";
const CREDITCARDS_USED_STATUS_PREF = "extensions.formautofill.creditCards.used";
const CREDITCARDS_AUTOFILL_SUPPORTED_COUNTRIES_PREF =
"extensions.formautofill.creditCards.supportedCountries";
const ENABLED_AUTOFILL_ADDRESSES_PREF =
"extensions.formautofill.addresses.enabled";
const ENABLED_AUTOFILL_ADDRESSES_CAPTURE_PREF =
"extensions.formautofill.addresses.capture.enabled";
const ENABLED_AUTOFILL_ADDRESSES_SUPPORTED_COUNTRIES_PREF =
"extensions.formautofill.addresses.supportedCountries";
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";
const FORM_AUTOFILL_SUPPORT_RTL_PREF = "extensions.formautofill.supportRTL";
XPCOMUtils.defineLazyPreferenceGetter(
this,
@ -66,18 +74,77 @@ var FormAutofill = {
get DEFAULT_REGION() {
return Region.home || "US";
},
/**
* Determines if an autofill feature should be enabled based on the "available"
* and "supportedCountries" parameters.
*
* @param {string} available Available can be one of the following: "on", "detect", "off".
* "on" forces the particular Form Autofill feature on, while "detect" utilizes the supported countries
* to see if the feature should be available.
* @param {string[]} supportedCountries
* @returns {boolean} `true` if autofill feature is supported in the current browser search region
*/
_isSupportedRegion(available, supportedCountries) {
if (available == "on") {
return true;
} else if (available == "detect") {
if (!FormAutofill.supportRTL && Services.locale.isAppLocaleRTL) {
return false;
}
let region = Services.prefs.getCharPref(BROWSER_SEARCH_REGION_PREF, "");
return supportedCountries.includes(region);
}
return false;
},
isAutofillAddressesAvailableInCountry(country) {
return FormAutofill._addressAutofillSupportedCountries.includes(country);
},
get isAutofillEnabled() {
return (
FormAutofill.isAutofillAddressesEnabled ||
this.isAutofillCreditCardsEnabled
return this.isAutofillAddressesEnabled || this.isAutofillCreditCardsEnabled;
},
/**
* Determines if the credit card autofill feature is available to use in the browser.
* If the feature is not available, then there are no user facing ways to enable it.
* @returns {boolean} `true` if credit card autofill is available
*/
get isAutofillCreditCardsAvailable() {
return this._isSupportedRegion(
FormAutofill._isAutofillCreditCardsAvailable,
FormAutofill._creditCardAutofillSupportedCountries
);
},
/**
* Determines if the address autofill feature is available to use in the browser.
* If the feature is not available, then there are no user facing ways to enable it.
* @returns {boolean} `true` if address autofill is available
*/
get isAutofillAddressesAvailable() {
return this._isSupportedRegion(
FormAutofill._isAutofillAddressesAvailable,
FormAutofill._addressAutofillSupportedCountries
);
},
/**
* Determines if the user has enabled or disabled credit card autofill.
* @returns {boolean} `true` if credit card autofill is enabled
*/
get isAutofillCreditCardsEnabled() {
return (
FormAutofill.isAutofillCreditCardsAvailable &&
this.isAutofillCreditCardsAvailable &&
FormAutofill._isAutofillCreditCardsEnabled
);
},
/**
* Determines if the user has enabled or disabled address autofill.
* @returns {boolean} `true` if address autofill is enabled
*/
get isAutofillAddressesEnabled() {
return (
this.isAutofillAddressesAvailable &&
FormAutofill._isAutofillAddressesEnabled
);
},
defineLazyLogGetter(scope, logPrefix) {
scope.debug = debug;
@ -97,7 +164,12 @@ var FormAutofill = {
XPCOMUtils.defineLazyPreferenceGetter(
FormAutofill,
"isAutofillAddressesEnabled",
"_isAutofillAddressesAvailable",
AUTOFILL_ADDRESSES_AVAILABLE_PREF
);
XPCOMUtils.defineLazyPreferenceGetter(
FormAutofill,
"_isAutofillAddressesEnabled",
ENABLED_AUTOFILL_ADDRESSES_PREF
);
XPCOMUtils.defineLazyPreferenceGetter(
@ -107,12 +179,12 @@ XPCOMUtils.defineLazyPreferenceGetter(
);
XPCOMUtils.defineLazyPreferenceGetter(
FormAutofill,
"isAutofillCreditCardsAvailable",
"_isAutofillCreditCardsAvailable",
AUTOFILL_CREDITCARDS_AVAILABLE_PREF
);
XPCOMUtils.defineLazyPreferenceGetter(
FormAutofill,
"isAutofillCreditCardsEnabled",
"_isAutofillCreditCardsEnabled",
ENABLED_AUTOFILL_CREDITCARDS_PREF
);
XPCOMUtils.defineLazyPreferenceGetter(
@ -132,12 +204,24 @@ XPCOMUtils.defineLazyPreferenceGetter(
);
XPCOMUtils.defineLazyPreferenceGetter(
FormAutofill,
"supportedCountries",
SUPPORTED_COUNTRIES_PREF,
"_addressAutofillSupportedCountries",
ENABLED_AUTOFILL_ADDRESSES_SUPPORTED_COUNTRIES_PREF,
null,
val => val.split(",")
);
XPCOMUtils.defineLazyPreferenceGetter(
FormAutofill,
"_creditCardAutofillSupportedCountries",
CREDITCARDS_AUTOFILL_SUPPORTED_COUNTRIES_PREF,
null,
null,
val => val.split(",")
);
XPCOMUtils.defineLazyPreferenceGetter(
FormAutofill,
"supportRTL",
FORM_AUTOFILL_SUPPORT_RTL_PREF
);
// XXX: This should be invalidated on intl:app-locales-changed.
XPCOMUtils.defineLazyGetter(FormAutofill, "countries", () => {

View File

@ -763,7 +763,7 @@ class FormAutofillAddressSection extends FormAutofillSection {
isRecordCreatable(record) {
if (
record.country &&
!FormAutofill.supportedCountries.includes(record.country)
!FormAutofill.isAutofillAddressesAvailableInCountry(record.country)
) {
// We don't want to save data in the wrong fields due to not having proper
// heuristic regexes in countries we don't yet support.

View File

@ -441,7 +441,7 @@ class FormAutofillParent extends JSWindowActorParent {
if (
collectionName == ADDRESSES_COLLECTION_NAME &&
record.country &&
!FormAutofill.supportedCountries.includes(record.country)
!FormAutofill.isAutofillAddressesAvailableInCountry(record.country)
) {
// Address autofill isn't supported for the record's country so we don't
// want to attempt to potentially incorrectly fill the address fields.