Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import {
InlineMenuElementPosition,
InlineMenuPosition,
Expand Down Expand Up @@ -62,8 +60,8 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte
*/
private inlineMenuEnabled = true;
private mutationObserverIterations = 0;
private mutationObserverIterationsResetTimeout: number | NodeJS.Timeout;
private handlePersistentLastChildOverrideTimeout: number | NodeJS.Timeout;
private mutationObserverIterationsResetTimeout: number | NodeJS.Timeout | null = null;
private handlePersistentLastChildOverrideTimeout: number | NodeJS.Timeout | null = null;
private lastElementOverrides: WeakMap<Element, number> = new WeakMap();
private readonly customElementDefaultStyles: Partial<CSSStyleDeclaration> = {
all: "initial",
Expand All @@ -77,7 +75,15 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte
};

constructor() {
this.setupMutationObserver();
this.htmlMutationObserver = new MutationObserver(this.handlePageMutations);
this.bodyMutationObserver = new MutationObserver(this.handlePageMutations);
this.inlineMenuElementsMutationObserver = new MutationObserver(
this.handleInlineMenuElementMutationObserverUpdate,
);
this.containerElementMutationObserver = new MutationObserver(
this.handleContainerElementMutationObserverUpdate,
);
this.observePageAttributes();
}

/**
Expand Down Expand Up @@ -181,12 +187,8 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte
* Updates the position of the inline menu button.
*/
private async appendButtonElement(): Promise<void> {
if (!this.inlineMenuEnabled) {
return;
}

if (!this.buttonElement) {
this.createButtonElement();
this.buttonElement = this.createButtonElement();
this.updateCustomElementDefaultStyles(this.buttonElement);
}

Expand All @@ -201,12 +203,8 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte
* Updates the position of the inline menu list.
*/
private async appendListElement(): Promise<void> {
if (!this.inlineMenuEnabled) {
return;
}

if (!this.listElement) {
this.createListElement();
this.listElement = this.createListElement();
this.updateCustomElementDefaultStyles(this.listElement);
}

Expand Down Expand Up @@ -257,16 +255,12 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte
* to create the element if it already exists in the DOM.
*/
private createButtonElement() {
if (!this.inlineMenuEnabled) {
return;
}

if (this.isFirefoxBrowser) {
this.buttonElement = globalThis.document.createElement("div");
this.buttonElement.setAttribute("popover", "manual");
new AutofillInlineMenuButtonIframe(this.buttonElement);

return;
return this.buttonElement;
}

const customElementName = this.generateRandomCustomElementName();
Expand All @@ -282,23 +276,20 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte

this.buttonElement = globalThis.document.createElement(customElementName);
this.buttonElement.setAttribute("popover", "manual");
return this.buttonElement;
}

/**
* Creates the autofill inline menu list element. Will not attempt
* to create the element if it already exists in the DOM.
*/
private createListElement() {
if (!this.inlineMenuEnabled) {
return;
}

if (this.isFirefoxBrowser) {
this.listElement = globalThis.document.createElement("div");
this.listElement.setAttribute("popover", "manual");
new AutofillInlineMenuListIframe(this.listElement);

return;
return this.listElement;
}

const customElementName = this.generateRandomCustomElementName();
Expand All @@ -314,6 +305,7 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte

this.listElement = globalThis.document.createElement(customElementName);
this.listElement.setAttribute("popover", "manual");
return this.listElement;
}

/**
Expand All @@ -330,27 +322,6 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte
this.observeCustomElements();
}

/**
* Sets up mutation observers for the inline menu elements, the menu container, and
* the document element. The mutation observers are used to remove any styles that
* are added to the inline menu elements by the website. They are also used to ensure
* that the inline menu elements are always present at the bottom of the menu container.
*/
private setupMutationObserver = () => {
this.htmlMutationObserver = new MutationObserver(this.handlePageMutations);
this.bodyMutationObserver = new MutationObserver(this.handlePageMutations);

this.inlineMenuElementsMutationObserver = new MutationObserver(
this.handleInlineMenuElementMutationObserverUpdate,
);

this.containerElementMutationObserver = new MutationObserver(
this.handleContainerElementMutationObserverUpdate,
);

this.observePageAttributes();
};

/**
* Sets up mutation observers to verify that the inline menu
* elements are not modified by the website.
Expand Down Expand Up @@ -652,6 +623,10 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte
return;
}

if (!this.buttonElement) {
return;
}

const lastChild = containerElement.lastElementChild;
const secondToLastChild = lastChild?.previousElementSibling;
const lastChildIsInlineMenuList = lastChild === this.listElement;
Expand All @@ -667,7 +642,8 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte
this.lastElementOverrides.set(lastChild, lastChildEncounterCount + 1);
}

if (this.lastElementOverrides.get(lastChild) >= 3) {
const lastChildEncounterCountAfterUpdate = this.lastElementOverrides.get(lastChild) || 0;
if (lastChildEncounterCountAfterUpdate >= 3) {
this.handlePersistentLastChildOverride(lastChild);

return;
Expand All @@ -686,6 +662,9 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte
(lastChildIsInlineMenuList && !secondToLastChildIsInlineMenuButton) ||
(lastChildIsInlineMenuButton && isInlineMenuListVisible)
) {
if (!this.listElement) {
return;
}
containerElement.insertBefore(this.buttonElement, this.listElement);
return;
}
Expand Down
Loading