1
0
mirror of https://github.com/bitwarden/browser.git synced 2025-01-24 21:41:33 +01:00

[PM-5189] Adding documentation for the AutofillOverlayContentService

This commit is contained in:
Cesar Gonzalez 2024-06-20 08:47:44 -05:00
parent 8138309039
commit 23c40d4a34
No known key found for this signature in database
GPG Key ID: 3381A5457F8CCECF
2 changed files with 47 additions and 51 deletions

View File

@ -28,15 +28,6 @@ describe("AutofillOverlayContentService", () => {
let autofillOverlayContentService: AutofillOverlayContentService;
let sendExtensionMessageSpy: jest.SpyInstance;
const sendResponseSpy = jest.fn();
beforeAll(() => {
const mockPerformanceObserver = jest.fn();
mockPerformanceObserver.mockReturnValue({
observe: jest.fn(),
disconnect: jest.fn(),
});
// @ts-expect-error Need to mock the performance observer
global.PerformanceObserver = mockPerformanceObserver;
});
beforeEach(() => {
inlineMenuFieldQualificationService = new InlineMenuFieldQualificationService();

View File

@ -126,26 +126,6 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
await this.setupInlineMenuOnQualifiedField(formFieldElement);
}
private async setupInlineMenuOnQualifiedField(
formFieldElement: ElementWithOpId<FormFieldElement>,
) {
this.formFieldElements.add(formFieldElement);
if (!this.mostRecentlyFocusedField) {
await this.updateMostRecentlyFocusedField(formFieldElement);
}
if (!this.inlineMenuVisibility) {
await this.getInlineMenuVisibility();
}
this.setupFormFieldElementEventListeners(formFieldElement);
if (this.getRootNodeActiveElement(formFieldElement) === formFieldElement) {
await this.triggerFormFieldFocusedAction(formFieldElement);
}
}
/**
* Handles opening the autofill inline menu. Will conditionally open
* the inline menu based on the current inline menu visibility setting.
@ -741,6 +721,31 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
this.removeHiddenFieldFallbackListener(formFieldElement);
};
/**
* Sets up the inline menu on a qualified form field element.
*
* @param formFieldElement - The form field element to set up the inline menu on.
*/
private async setupInlineMenuOnQualifiedField(
formFieldElement: ElementWithOpId<FormFieldElement>,
) {
this.formFieldElements.add(formFieldElement);
if (!this.mostRecentlyFocusedField) {
await this.updateMostRecentlyFocusedField(formFieldElement);
}
if (!this.inlineMenuVisibility) {
await this.getInlineMenuVisibility();
}
this.setupFormFieldElementEventListeners(formFieldElement);
if (this.getRootNodeActiveElement(formFieldElement) === formFieldElement) {
await this.triggerFormFieldFocusedAction(formFieldElement);
}
}
/**
* Queries the background script for the autofill inline menu visibility setting.
* If the setting is not found, a default value of OnFieldFocus will be used
@ -811,14 +816,6 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
return (await this.sendExtensionMessage("checkIsInlineMenuCiphersPopulated")) === true;
}
/**
* Triggers a validation to ensure that the inline menu is repositioned only when the
* current frame contains the focused field at any given depth level.
*/
private async checkShouldRepositionInlineMenu() {
return (await this.sendExtensionMessage("checkShouldRepositionInlineMenu")) === true;
}
/**
* Gets the root node of the passed element and returns the active element within that root node.
*
@ -1048,6 +1045,10 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
await this.sendExtensionMessage("triggerAutofillOverlayReposition");
};
/**
* Sets up listeners that facilitate a rebuild of the sub frame offsets
* when a user interacts or focuses an element within the frame.
*/
private setupRebuildSubFrameOffsetsListeners = () => {
if (globalThis.window.top === globalThis.window || this.formFieldElements.size < 1) {
return;
@ -1057,6 +1058,11 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
globalThis.document.body.addEventListener(EVENTS.MOUSEENTER, this.handleSubFrameFocusInEvent);
};
/**
* Sends a message to the background script to trigger a rebuild of the sub frame
* offsets. Will deregister the listeners to ensure that other focus and mouse
* events do not unnecessarily re-trigger a sub frame rebuild.
*/
private handleSubFrameFocusInEvent = () => {
void this.sendExtensionMessage("triggerSubFrameFocusInRebuild");
@ -1072,17 +1078,14 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
);
};
/**
* Triggers an update in the most recently focused field's data and returns
* whether the field is within the viewport bounds. If not within the bounds
* of the viewport, the inline menu will be closed.
*/
private async checkIsMostRecentlyFocusedFieldWithinViewport() {
await this.updateMostRecentlyFocusedField(this.mostRecentlyFocusedField);
return this.isFocusedFieldWithinViewportBounds();
}
/**
* Checks if the focused field is present within the bounds of the viewport.
* If not present, the inline menu will be closed.
*/
private isFocusedFieldWithinViewportBounds() {
const focusedFieldRectsTop = this.focusedFieldData?.focusedFieldRects?.top;
const focusedFieldRectsBottom =
focusedFieldRectsTop + this.focusedFieldData?.focusedFieldRects?.height;
@ -1095,29 +1098,31 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
);
}
/**
* Clears the timeout that triggers a debounced focus of the inline menu list.
*/
private clearFocusInlineMenuListTimeout() {
if (this.focusInlineMenuListTimeout) {
globalThis.clearTimeout(this.focusInlineMenuListTimeout);
}
}
/**
* Clears the timeout that triggers the closing of the inline menu on a focus redirection.
*/
private clearCloseInlineMenuOnRedirectTimeout() {
if (this.closeInlineMenuOnRedirectTimeout) {
globalThis.clearTimeout(this.closeInlineMenuOnRedirectTimeout);
}
}
private clearAllTimeouts() {
this.clearFocusInlineMenuListTimeout();
this.clearCloseInlineMenuOnRedirectTimeout();
}
/**
* Destroys the autofill overlay content service. This method will
* disconnect the mutation observers and remove all event listeners.
*/
destroy() {
this.clearAllTimeouts();
this.clearFocusInlineMenuListTimeout();
this.clearCloseInlineMenuOnRedirectTimeout();
this.formFieldElements.forEach((formFieldElement) => {
this.removeCachedFormFieldEventListeners(formFieldElement);
formFieldElement.removeEventListener(EVENTS.BLUR, this.handleFormFieldBlurEvent);