mirror of
https://github.com/bitwarden/browser.git
synced 2025-01-21 21:11:35 +01:00
[PM-4923] Form elements that fade into view contain incorrectly cached page details (#6953)
* [PM-4923] Form Elements that Fade into View Contain Incorrectly Cached Page Details * [PM-4923] Form Elements that Fade into View Contain Incorrectly Cached Page Details * [PM-4923] Running prettier on implementation
This commit is contained in:
parent
51c5e053f7
commit
dafb251cac
@ -2051,6 +2051,83 @@ describe("CollectAutofillContentService", () => {
|
||||
collectAutofillContentService["handleAutofillElementAttributeMutation"],
|
||||
).not.toBeCalled();
|
||||
});
|
||||
|
||||
it("will setup the overlay listeners on mutated elements", async () => {
|
||||
jest.useFakeTimers();
|
||||
const form = document.createElement("form");
|
||||
document.body.appendChild(form);
|
||||
const addedNodes = document.querySelectorAll("form");
|
||||
const removedNodes = document.querySelectorAll("li");
|
||||
const mutationRecord: MutationRecord = {
|
||||
type: "childList",
|
||||
addedNodes: addedNodes,
|
||||
attributeName: null,
|
||||
attributeNamespace: null,
|
||||
nextSibling: null,
|
||||
oldValue: null,
|
||||
previousSibling: null,
|
||||
removedNodes: removedNodes,
|
||||
target: document.body,
|
||||
};
|
||||
collectAutofillContentService["domRecentlyMutated"] = false;
|
||||
collectAutofillContentService["noFieldsFound"] = true;
|
||||
collectAutofillContentService["currentLocationHref"] = window.location.href;
|
||||
jest.spyOn(collectAutofillContentService as any, "setupOverlayListenersOnMutatedElements");
|
||||
|
||||
collectAutofillContentService["handleMutationObserverMutation"]([mutationRecord]);
|
||||
jest.runAllTimers();
|
||||
|
||||
expect(collectAutofillContentService["setupOverlayListenersOnMutatedElements"]).toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("setupOverlayListenersOnMutatedElements", () => {
|
||||
it("skips building the autofill field item if the node is not a form field element", () => {
|
||||
const divElement = document.createElement("div");
|
||||
const nodes = [divElement];
|
||||
jest.spyOn(collectAutofillContentService as any, "buildAutofillFieldItem");
|
||||
|
||||
collectAutofillContentService["setupOverlayListenersOnMutatedElements"](nodes);
|
||||
|
||||
expect(collectAutofillContentService["buildAutofillFieldItem"]).not.toBeCalled();
|
||||
});
|
||||
|
||||
it("skips building the autofill field item if the node is already a field element", () => {
|
||||
const inputElement = document.createElement("input") as ElementWithOpId<HTMLInputElement>;
|
||||
inputElement.setAttribute("type", "password");
|
||||
const nodes = [inputElement];
|
||||
collectAutofillContentService["autofillFieldElements"].set(inputElement, {
|
||||
opid: "1234",
|
||||
} as AutofillField);
|
||||
jest.spyOn(collectAutofillContentService as any, "buildAutofillFieldItem");
|
||||
|
||||
collectAutofillContentService["setupOverlayListenersOnMutatedElements"](nodes);
|
||||
|
||||
expect(collectAutofillContentService["buildAutofillFieldItem"]).not.toBeCalled();
|
||||
});
|
||||
|
||||
it("builds the autofill field item to ensure the overlay listeners are set", () => {
|
||||
document.body.innerHTML = `
|
||||
<form>
|
||||
<label for="username-id">Username Label</label>
|
||||
<input type="text" id="username-id">
|
||||
</form>
|
||||
`;
|
||||
|
||||
const inputElement = document.getElementById(
|
||||
"username-id",
|
||||
) as ElementWithOpId<HTMLInputElement>;
|
||||
inputElement.setAttribute("type", "password");
|
||||
const nodes = [inputElement];
|
||||
jest.spyOn(collectAutofillContentService as any, "buildAutofillFieldItem");
|
||||
|
||||
collectAutofillContentService["setupOverlayListenersOnMutatedElements"](nodes);
|
||||
|
||||
expect(collectAutofillContentService["buildAutofillFieldItem"]).toBeCalledWith(
|
||||
inputElement,
|
||||
-1,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("deleteCachedAutofillElement", () => {
|
||||
|
@ -303,7 +303,7 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
|
||||
element.opid = `__${index}`;
|
||||
|
||||
const existingAutofillField = this.autofillFieldElements.get(element);
|
||||
if (existingAutofillField) {
|
||||
if (index >= 0 && existingAutofillField) {
|
||||
existingAutofillField.opid = element.opid;
|
||||
existingAutofillField.elementNumber = index;
|
||||
this.autofillFieldElements.set(element, existingAutofillField);
|
||||
@ -325,7 +325,7 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
|
||||
};
|
||||
|
||||
if (element instanceof HTMLSpanElement) {
|
||||
this.autofillFieldElements.set(element, autofillFieldBase);
|
||||
this.cacheAutofillFieldElement(index, element, autofillFieldBase);
|
||||
this.autofillOverlayContentService?.setupAutofillOverlayListenerOnField(
|
||||
element,
|
||||
autofillFieldBase,
|
||||
@ -366,11 +366,31 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
|
||||
"data-stripe": this.getPropertyOrAttribute(element, "data-stripe"),
|
||||
};
|
||||
|
||||
this.autofillFieldElements.set(element, autofillField);
|
||||
this.cacheAutofillFieldElement(index, element, autofillField);
|
||||
this.autofillOverlayContentService?.setupAutofillOverlayListenerOnField(element, autofillField);
|
||||
return autofillField;
|
||||
};
|
||||
|
||||
/**
|
||||
* Caches the autofill field element and its data.
|
||||
* Will not cache the element if the index is less than 0.
|
||||
*
|
||||
* @param index - The index of the autofill field element
|
||||
* @param element - The autofill field element to cache
|
||||
* @param autofillFieldData - The autofill field data to cache
|
||||
*/
|
||||
private cacheAutofillFieldElement(
|
||||
index: number,
|
||||
element: ElementWithOpId<FormFieldElement>,
|
||||
autofillFieldData: AutofillField,
|
||||
) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.autofillFieldElements.set(element, autofillFieldData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies the autocomplete attribute associated with an element and returns
|
||||
* the value of the attribute if it is not set to "off".
|
||||
@ -987,7 +1007,7 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
|
||||
}
|
||||
|
||||
let isElementMutated = false;
|
||||
const mutatedElements = [];
|
||||
const mutatedElements: Node[] = [];
|
||||
for (let index = 0; index < nodes.length; index++) {
|
||||
const node = nodes[index];
|
||||
if (!(node instanceof HTMLElement)) {
|
||||
@ -1010,17 +1030,31 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
|
||||
}
|
||||
}
|
||||
|
||||
for (let elementIndex = 0; elementIndex < mutatedElements.length; elementIndex++) {
|
||||
const node = mutatedElements[elementIndex];
|
||||
if (isRemovingNodes) {
|
||||
if (isRemovingNodes) {
|
||||
for (let elementIndex = 0; elementIndex < mutatedElements.length; elementIndex++) {
|
||||
const node = mutatedElements[elementIndex];
|
||||
this.deleteCachedAutofillElement(
|
||||
node as ElementWithOpId<HTMLFormElement> | ElementWithOpId<FormFieldElement>,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
} else if (this.autofillOverlayContentService) {
|
||||
setTimeout(() => this.setupOverlayListenersOnMutatedElements(mutatedElements), 1000);
|
||||
}
|
||||
|
||||
return isElementMutated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the overlay listeners on the passed mutated elements. This ensures
|
||||
* that the overlay can appear on elements that are injected into the DOM after
|
||||
* the initial page load.
|
||||
*
|
||||
* @param mutatedElements - HTML elements that have been mutated
|
||||
*/
|
||||
private setupOverlayListenersOnMutatedElements(mutatedElements: Node[]) {
|
||||
for (let elementIndex = 0; elementIndex < mutatedElements.length; elementIndex++) {
|
||||
const node = mutatedElements[elementIndex];
|
||||
if (
|
||||
this.autofillOverlayContentService &&
|
||||
this.isNodeFormFieldElement(node) &&
|
||||
!this.autofillFieldElements.get(node as ElementWithOpId<FormFieldElement>)
|
||||
) {
|
||||
@ -1029,8 +1063,6 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
|
||||
this.buildAutofillFieldItem(node as ElementWithOpId<FormFieldElement>, -1);
|
||||
}
|
||||
}
|
||||
|
||||
return isElementMutated;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user