Backed out 7 changesets (bug 1863801, bug 1865876) for causing failures in browser_creditCard_doorhanger_iframe.js CLOSED TREE

Backed out changeset 395e2da83ee8 (bug 1865876)
Backed out changeset c27de56bd433 (bug 1863801)
Backed out changeset 8d297207efc7 (bug 1863801)
Backed out changeset 193d5c08a17f (bug 1863801)
Backed out changeset dd78261ec1d8 (bug 1863801)
Backed out changeset 5f6ad20da89e (bug 1863801)
Backed out changeset 31e08bae4ce6 (bug 1863801)
This commit is contained in:
Noemi Erli 2023-12-01 22:16:15 +02:00
Родитель 0497852ff8
Коммит cb5c9fb296
16 изменённых файлов: 24 добавлений и 434 удалений

Просмотреть файл

@ -10,8 +10,6 @@ support-files = [
"head_address.js",
]
["browser_address_capture_form_removal.js"]
["browser_address_doorhanger_display.js"]
["browser_address_doorhanger_not_shown.js"]

Просмотреть файл

@ -1,124 +0,0 @@
"use strict";
async function expectSavedAddresses(expectedAddresses) {
const addresses = await getAddresses();
is(
addresses.length,
expectedAddresses.length,
`${addresses.length} address in the storage`
);
for (let i = 0; i < expectedAddresses.length; i++) {
for (const [key, value] of Object.entries(expectedAddresses[i])) {
is(addresses[i][key] ?? "", value, `field ${key} should be equal`);
}
}
return addresses;
}
const ADDRESS_FIELD_VALUES = {
"given-name": "Test User",
organization: "Sesame Street",
"street-address": "123 Sesame Street",
};
add_setup(async function () {
await SpecialPowers.pushPrefEnv({
set: [
["extensions.formautofill.addresses.capture.v2.enabled", true],
["extensions.formautofill.addresses.supported", "on"],
["extensions.formautofill.heuristics.captureOnFormRemoval", true],
],
});
await removeAllRecords();
});
/**
* Tests if the address is captured (address doorhanger is shown) after a
* successful xhr or fetch request followed by a form removal and
* that the stored address record has the right values.
*/
add_task(async function test_address_captured_after_form_removal() {
const onStorageChanged = waitForStorageChangedEvents("add");
await BrowserTestUtils.withNewTab(
{ gBrowser, url: ADDRESS_FORM_URL },
async function (browser) {
const onPopupShown = waitForPopupShown();
info("Update identified address fields");
// We don't submit the form
await focusUpdateSubmitForm(
browser,
{
focusSelector: "#given-name",
newValues: {
"#given-name": ADDRESS_FIELD_VALUES["given-name"],
"#organization": ADDRESS_FIELD_VALUES.organization,
"#street-address": ADDRESS_FIELD_VALUES["street-address"],
},
},
false
);
info("Infer a successfull fetch request");
await SpecialPowers.spawn(browser, [], async () => {
await content.fetch(
"https://example.org/browser/browser/extensions/formautofill/test/browser/empty.html"
);
});
info("Infer form removal");
await SpecialPowers.spawn(browser, [], async function () {
let form = content.document.getElementById("form");
form.parentNode.remove(form);
});
info("Wait for address doorhanger");
await onPopupShown;
info("Click Save in address doorhanger");
await clickDoorhangerButton(MAIN_BUTTON, 0);
}
);
info("Wait for the address to be added to the storage.");
await onStorageChanged;
info("Ensure that address record was captured and saved correctly.");
await expectSavedAddresses([ADDRESS_FIELD_VALUES]);
await removeAllRecords();
});
/**
* Tests that the address is not captured without a prior fetch or xhr request event
*/
add_task(async function test_address_not_captured_without_prior_fetch() {
await BrowserTestUtils.withNewTab(
{ gBrowser, url: ADDRESS_FORM_URL },
async function (browser) {
info("Update identified address fields");
// We don't submit the form
await focusUpdateSubmitForm(
browser,
{
focusSelector: "#given-name",
newValues: {
"#given-name": ADDRESS_FIELD_VALUES["given-name"],
"#organization": ADDRESS_FIELD_VALUES.organization,
"#street-address": ADDRESS_FIELD_VALUES["street-address"],
},
},
false
);
info("Infer form removal");
await SpecialPowers.spawn(browser, [], async function () {
let form = content.document.getElementById("form");
form.parentNode.remove(form);
});
info("Ensure that address doorhanger is not shown");
await ensureNoDoorhanger(browser);
}
);
});

Просмотреть файл

@ -17,8 +17,6 @@ support-files = [
["browser_anti_clickjacking.js"]
skip-if = ["!debug && os == 'mac'"] # perma-fail see Bug 1600059
["browser_creditCard_capture_form_removal.js"]
["browser_creditCard_doorhanger_action.js"]
skip-if = [
"!debug && os == 'mac'", # perma-fail see Bug 1655601

Просмотреть файл

@ -1,115 +0,0 @@
"use strict";
const CC_VALUES = {
"cc-name": "User",
"cc-number": "5577000055770004",
"cc-exp-month": 12,
"cc-exp-year": 2017,
};
add_setup(async function () {
await SpecialPowers.pushPrefEnv({
set: [["extensions.formautofill.heuristics.captureOnFormRemoval", true]],
});
await removeAllRecords();
});
/**
* Tests if the credit card is captured (cc doorhanger is shown) after a
* successful xhr or fetch request followed by a form removal and
* that the stored credit card record has the right values.
*/
add_task(async function test_credit_card_captured_after_form_removal() {
const onStorageChanged = waitForStorageChangedEvents("add");
await BrowserTestUtils.withNewTab(
{ gBrowser, url: CREDITCARD_FORM_URL },
async function (browser) {
const onPopupShown = waitForPopupShown();
info("Update identified credit card fields");
// We don't submit the form
await focusUpdateSubmitForm(
browser,
{
focusSelector: "#cc-name",
newValues: {
"#cc-name": CC_VALUES["cc-name"],
"#cc-number": CC_VALUES["cc-number"],
"#cc-exp-month": CC_VALUES["cc-exp-month"],
"#cc-exp-year": CC_VALUES["cc-exp-year"],
},
},
false
);
info("Infer a successfull fetch request");
await SpecialPowers.spawn(browser, [], async () => {
await content.fetch(
"https://example.org/browser/browser/extensions/formautofill/test/browser/empty.html"
);
});
info("Infer form removal");
await SpecialPowers.spawn(browser, [], async function () {
let form = content.document.getElementById("form");
form.parentNode.remove(form);
});
info("Wait for credit card doorhanger");
await onPopupShown;
info("Click Save in credit card doorhanger");
await clickDoorhangerButton(MAIN_BUTTON);
}
);
info("Wait for the credit card to be added to the storage.");
await onStorageChanged;
const storedCreditCards = await getCreditCards();
let actualCreditCard = storedCreditCards[0];
actualCreditCard["cc-number"] = await OSKeyStore.decrypt(
actualCreditCard["cc-number-encrypted"]
);
for (let key in CC_VALUES) {
let expected = CC_VALUES[key];
let actual = actualCreditCard[key];
is(expected, actual, `${key} should be equal`);
}
await removeAllRecords();
});
/**
* Tests that the credit card is not captured without a prior fetch or xhr request event
*/
add_task(async function test_credit_card_not_captured_without_prior_fetch() {
await BrowserTestUtils.withNewTab(
{ gBrowser, url: CREDITCARD_FORM_URL },
async function (browser) {
info("Update identified credit card fields");
// We don't submit the form
await focusUpdateSubmitForm(
browser,
{
focusSelector: "#cc-name",
newValues: {
"#cc-name": CC_VALUES["cc-name"],
"#cc-number": CC_VALUES["cc-number"],
"#cc-exp-month": CC_VALUES["cc-exp-month"],
"#cc-exp-year": CC_VALUES["cc-exp-year"],
},
},
false
);
info("Infer form removal");
await SpecialPowers.spawn(browser, [], async function () {
let form = content.document.getElementById("form");
form.parentNode.remove(form);
});
info("Ensure that credit card doorhanger is not shown");
await ensureNoDoorhanger(browser);
}
);
});

Просмотреть файл

@ -563,7 +563,7 @@ add_task(async function handle_invalid_form() {
let fakeForm = doc.createElement("form");
sinon.spy(FormAutofillContent, "_onFormSubmit");
FormAutofillContent.formSubmitted(fakeForm, undefined, null);
FormAutofillContent.formSubmitted(fakeForm, null);
Assert.equal(FormAutofillContent._onFormSubmit.called, false);
FormAutofillContent._onFormSubmit.restore();
});
@ -602,7 +602,7 @@ add_task(async function autofill_disabled() {
"extensions.formautofill.creditCards.enabled",
false
);
FormAutofillContent.formSubmitted(form, undefined, null);
FormAutofillContent.formSubmitted(form, null);
Assert.equal(FormAutofillContent._onFormSubmit.called, false);
FormAutofillContent._onFormSubmit.resetHistory();
@ -615,7 +615,7 @@ add_task(async function autofill_disabled() {
true
);
FormAutofillContent.formSubmitted(form, undefined, null);
FormAutofillContent.formSubmitted(form, null);
Assert.equal(FormAutofillContent._onFormSubmit.called, true);
Assert.notDeepEqual(FormAutofillContent._onFormSubmit.args[0][0].address, []);
Assert.notDeepEqual(
@ -629,7 +629,7 @@ add_task(async function autofill_disabled() {
"extensions.formautofill.addresses.enabled",
false
);
FormAutofillContent.formSubmitted(form, undefined, null);
FormAutofillContent.formSubmitted(form, null);
Assert.equal(FormAutofillContent._onFormSubmit.called, true);
Assert.deepEqual(FormAutofillContent._onFormSubmit.args[0][0].address, []);
Assert.notDeepEqual(
@ -644,7 +644,7 @@ add_task(async function autofill_disabled() {
"extensions.formautofill.creditCards.enabled",
false
);
FormAutofillContent.formSubmitted(form, undefined, null);
FormAutofillContent.formSubmitted(form, null);
Assert.deepEqual(FormAutofillContent._onFormSubmit.called, true);
Assert.notDeepEqual(FormAutofillContent._onFormSubmit.args[0][0].address, []);
Assert.deepEqual(FormAutofillContent._onFormSubmit.args[0][0].creditCard, []);
@ -684,7 +684,7 @@ TESTCASES.forEach(testcase => {
let element = doc.getElementById(testcase.targetElementId);
FormAutofillContent.identifyAutofillFields(element);
FormAutofillContent.formSubmitted(form, undefined, null);
FormAutofillContent.formSubmitted(form, null);
Assert.equal(
FormAutofillContent._onFormSubmit.called,

Просмотреть файл

@ -3774,8 +3774,7 @@ class Document : public nsINode,
void SetNotifyFetchSuccess(bool aShouldNotify);
// When this is set, removing a form or a password field from DOM
// sends a Chrome-only event. This is now only used by the password manager
// and formautofill.
// sends a Chrome-only event. This is now only used by the password manager.
void SetNotifyFormOrPasswordRemoved(bool aShouldNotify);
// This function is used by HTMLFormElement and HTMLInputElement to determin

Просмотреть файл

@ -2111,9 +2111,9 @@ void HTMLFormElement::MaybeFireFormRemoved() {
return;
}
// Right now, only the password manager and formautofill listen to the event
// and only listen to it under certain circumstances. So don't fire this event
// unless necessary.
// Right now, only the password manager listens to the event and only listen
// to it under certain circumstances. So don't fire this event unless
// necessary.
if (!doc->ShouldNotifyFormOrPasswordRemoved()) {
return;
}

Просмотреть файл

@ -594,7 +594,7 @@ class HTMLFormElement final : public nsGenericHTMLElement,
/**
* Fire an event when the form is removed from the DOM tree. This is now only
* used by the password manager and formautofill.
* used by the password manager.
*/
void MaybeFireFormRemoved();

Просмотреть файл

@ -1626,7 +1626,7 @@ class HTMLInputElement final : public TextControlElement,
/**
* Fire an event when the password input field is removed from the DOM tree.
* This is now only used by the password manager and formautofill.
* This is now only used by the password manager.
*/
void MaybeFireInputPasswordRemoved();

Просмотреть файл

@ -3985,9 +3985,6 @@ pref("extensions.formautofill.creditCards.heuristics.fathom.highConfidenceThresh
pref("extensions.formautofill.creditCards.heuristics.fathom.testConfidence", "0");
pref("extensions.formautofill.loglevel", "Warn");
// Temporary pref that we will remove when enabling capture on form removal in Fx122.
pref("extensions.formautofill.heuristics.captureOnFormRemoval", false);
// The interactivityCheckMode pref is only temporary.
// It will be removed when we decide to only support the `focusability` mode
pref("extensions.formautofill.heuristics.interactivityCheckMode", "focusability");

Просмотреть файл

@ -30,7 +30,6 @@ const IOS_DEFAULT_PREFERENCES = {
// `IsFieldVisible` function doesn't use it
"extensions.formautofill.heuristics.visibilityCheckThreshold": 0,
"extensions.formautofill.heuristics.interactivityCheckMode": "focusability",
"extensions.formautofill.heuristics.captureOnFormRemoval": false,
"extensions.formautofill.focusOnAutofill": false,
};

Просмотреть файл

@ -32,14 +32,11 @@ const AUTOFILL_CREDITCARDS_AUTOCOMPLETE_OFF_PREF =
"extensions.formautofill.creditCards.ignoreAutocompleteOff";
const AUTOFILL_ADDRESSES_AUTOCOMPLETE_OFF_PREF =
"extensions.formautofill.addresses.ignoreAutocompleteOff";
const ENABLED_AUTOFILL_CAPTURE_ON_FORM_REMOVAL =
"extensions.formautofill.heuristics.captureOnFormRemoval";
export const FormAutofill = {
ENABLED_AUTOFILL_ADDRESSES_PREF,
ENABLED_AUTOFILL_ADDRESSES_CAPTURE_PREF,
ENABLED_AUTOFILL_ADDRESSES_CAPTURE_V2_PREF,
ENABLED_AUTOFILL_CAPTURE_ON_FORM_REMOVAL,
ENABLED_AUTOFILL_CREDITCARDS_PREF,
ENABLED_AUTOFILL_CREDITCARDS_REAUTH_PREF,
AUTOFILL_CREDITCARDS_AUTOCOMPLETE_OFF_PREF,
@ -255,11 +252,6 @@ XPCOMUtils.defineLazyPreferenceGetter(
"addressesAutocompleteOff",
AUTOFILL_ADDRESSES_AUTOCOMPLETE_OFF_PREF
);
XPCOMUtils.defineLazyPreferenceGetter(
FormAutofill,
"captureOnFormRemoval",
ENABLED_AUTOFILL_CAPTURE_ON_FORM_REMOVAL
);
// XXX: This should be invalidated on intl:app-locales-changed.
ChromeUtils.defineLazyGetter(FormAutofill, "countries", () => {

Просмотреть файл

@ -12,11 +12,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
setTimeout: "resource://gre/modules/Timer.sys.mjs",
});
export const FORM_SUBMISSION_REASON = {
FORM_SUBMIT_EVENT: "form-submit-event",
FORM_REMOVAL_AFTER_FETCH: "form-removal-after-fetch",
};
/**
* Handles content's interactions for the frame.
*/
@ -78,11 +73,6 @@ export class FormAutofillChild extends JSWindowActorChild {
}
}
/**
* Invokes the FormAutofillContent to identify the autofill fields
* and consider opening the dropdown menu for the focused field
*
*/
_doIdentifyAutofillFields() {
if (this._hasPendingTask) {
return;
@ -90,16 +80,7 @@ export class FormAutofillChild extends JSWindowActorChild {
this._hasPendingTask = true;
lazy.setTimeout(() => {
const isAnyFieldIdentified =
lazy.FormAutofillContent.identifyAutofillFields(
this._nextHandleElement
);
if (isAnyFieldIdentified && lazy.FormAutofill.captureOnFormRemoval) {
this.registerDOMDocFetchSuccessEventListener(
this._nextHandleElement.ownerDocument
);
}
lazy.FormAutofillContent.identifyAutofillFields(this._nextHandleElement);
this._hasPendingTask = false;
this._nextHandleElement = null;
// This is for testing purpose only which sends a notification to indicate that the
@ -109,67 +90,6 @@ export class FormAutofillChild extends JSWindowActorChild {
});
}
/**
* After a focusin event and after we identify formautofill fields,
* we set up an event listener for the DOMDocFetchSuccess event
*
* @param {Document} document The document we want to be notified by of a DOMDocFetchSuccess event
*/
registerDOMDocFetchSuccessEventListener(document) {
document.setNotifyFetchSuccess(true);
// Is removed after a DOMDocFetchSuccess event (bug 1864855)
/* eslint-disable mozilla/balanced-listeners */
this.docShell.chromeEventHandler.addEventListener(
"DOMDocFetchSuccess",
this,
true
);
}
/**
* After a DOMDocFetchSuccess event, we register an event listener for the DOMFormRemoved event
*
* @param {Document} document The document we want to be notified by of a DOMFormRemoved event
*/
registerDOMFormRemovedEventListener(document) {
document.setNotifyFormOrPasswordRemoved(true);
// Is removed after a DOMFormRemoved event (bug 1864855)
/* eslint-disable mozilla/balanced-listeners */
this.docShell.chromeEventHandler.addEventListener(
"DOMFormRemoved",
this,
true
);
}
/**
* After a DOMDocFetchSuccess event we remove the DOMDocFetchSuccess event listener
*
* @param {Document} document The document we are notified by of a DOMDocFetchSuccess event
*/
unregisterDOMDocFetchSuccessEventListener(document) {
document.setNotifyFetchSuccess(false);
this.docShell.chromeEventHandler.removeEventListener(
"DOMDocFetchSuccess",
this
);
}
/**
* After a DOMFormRemoved event we remove the DOMFormRemoved event listener
*
* @param {Document} document The document we are notified by of a DOMFormRemoved event
*/
unregisterDOMFormRemovedEventListener(document) {
document.setNotifyFormOrPasswordRemoved(false);
this.docShell.chromeEventHandler.removeEventListener(
"DOMFormRemoved",
this
);
}
shouldIgnoreFormAutofillEvent(event) {
let nodePrincipal = event.target.nodePrincipal;
return (
@ -183,6 +103,7 @@ export class FormAutofillChild extends JSWindowActorChild {
if (!evt.isTrusted) {
return;
}
if (this.shouldIgnoreFormAutofillEvent(evt)) {
return;
}
@ -200,14 +121,6 @@ export class FormAutofillChild extends JSWindowActorChild {
}
break;
}
case "DOMFormRemoved": {
this.onDOMFormRemoved(evt);
break;
}
case "DOMDocFetchSuccess": {
this.onDOMDocFetchSuccess(evt);
break;
}
default: {
throw new Error("Unexpected event type");
@ -249,47 +162,13 @@ export class FormAutofillChild extends JSWindowActorChild {
* @param {Event} evt
*/
onDOMFormBeforeSubmit(evt) {
const formElement = evt.target;
let formElement = evt.target;
lazy.FormAutofillContent.formSubmitted(
formElement,
FORM_SUBMISSION_REASON.FORM_SUBMIT_EVENT
);
}
if (!lazy.FormAutofill.isAutofillEnabled) {
return;
}
/**
* Handle the DOMFormRemoved event.
*
* Infers a form submission when the form is removed
* after a successful fetch or XHR request.
*
* @param {Event} evt DOMFormRemoved
*/
onDOMFormRemoved(evt) {
const document = evt.composedTarget.ownerDocument;
lazy.FormAutofillContent.formSubmitted(
evt.target,
FORM_SUBMISSION_REASON.FORM_REMOVAL_AFTER_FETCH
);
this.unregisterDOMFormRemovedEventListener(document);
}
/**
* Handle the DOMDocFetchSuccess event.
*
* Sets up an event listener for the DOMFormRemoved event
* and unregisters the event listener for DOMDocFetchSuccess event.
*
* @param {Event} evt DOMDocFetchSuccess
*/
onDOMDocFetchSuccess(evt) {
const document = evt.target;
this.registerDOMFormRemovedEventListener(document);
this.unregisterDOMDocFetchSuccessEventListener(document);
lazy.FormAutofillContent.formSubmitted(formElement);
}
receiveMessage(message) {

Просмотреть файл

@ -10,7 +10,6 @@
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
import { FORM_SUBMISSION_REASON } from "./FormAutofillChild.sys.mjs";
const lazy = {};
@ -136,19 +135,16 @@ export var FormAutofillContent = {
* 3. Number of filled fields is less than autofill threshold
*
* @param {HTMLElement} formElement Root element which receives submit event.
* @param {string} reason Reason for invoking the form submission
* (see options for FORM_SUBMISSION_REASON in FormAutofillChild))
* @param {Window} domWin Content window; passed for unit tests and when
* invoked by the FormAutofillSection
* @param {object} handler FormAutofillHander, if known by caller
*/
formSubmitted(
formElement,
reason = FORM_SUBMISSION_REASON.FORM_SUBMIT_EVENT,
domWin = formElement.ownerGlobal,
handler = undefined
) {
this.debug(`Handling form submission - derived from ${reason}`);
this.debug("Handling form submission");
if (!lazy.FormAutofill.isAutofillEnabled) {
this.debug("Form Autofill is disabled");
@ -270,15 +266,6 @@ export var FormAutofillContent = {
this._autofillPending = flag;
},
/**
* Identifies and marks each autofill field
*
* @param {HTMLElement} element
* Element that serves as an anchor for the formautofill heuristics to retrieve
* the root form and run the formautofill heuristics on the form elements
* @returns {boolean}
* whether any autofill fields were identified
*/
identifyAutofillFields(element) {
this.debug(
`identifyAutofillFields: ${element.ownerDocument.location?.hostname}`
@ -296,8 +283,6 @@ export var FormAutofillContent = {
this._fieldDetailsManager.identifyAutofillFields(element);
validDetails?.forEach(detail => this._markAsAutofillField(detail.element));
return !!validDetails.length;
},
clearForm() {

Просмотреть файл

@ -329,9 +329,7 @@ const observer = {
lazy.LoginHelper.formRemovalCaptureEnabled &&
(!alreadyModified || !alreadyModifiedFormLessField)
) {
loginManagerChild.registerDOMDocFetchSuccessEventListener(
ownerDocument
);
ownerDocument.setNotifyFetchSuccess(true);
}
if (
@ -1544,23 +1542,6 @@ export class LoginManagerChild extends JSWindowActorChild {
);
}
registerDOMDocFetchSuccessEventListener(document) {
document.setNotifyFetchSuccess(true);
this.docShell.chromeEventHandler.addEventListener(
"DOMDocFetchSuccess",
this,
true
);
}
unregisterDOMDocFetchSuccessEventListener(document) {
document.setNotifyFetchSuccess(false);
this.docShell.chromeEventHandler.removeEventListener(
"DOMDocFetchSuccess",
this
);
}
handleEvent(event) {
if (
AppConstants.platform == "android" &&
@ -1723,8 +1704,8 @@ export class LoginManagerChild extends JSWindowActorChild {
}
}
// Observers have been set up, remove the listener.
this.unregisterDOMDocFetchSuccessEventListener(document);
// Observers have been setted up, removed the listener.
document.setNotifyFetchSuccess(false);
}
/*

Просмотреть файл

@ -355,6 +355,7 @@ let JSWINDOWACTORS = {
child: {
esModuleURI: "resource://gre/modules/LoginManagerChild.sys.mjs",
events: {
DOMDocFetchSuccess: {},
DOMFormBeforeSubmit: {},
DOMFormHasPassword: {},
DOMFormHasPossibleUsername: {},