[PM-14045] Scrolling content outside of iframe bounds breaks inline menu position

This commit is contained in:
Cesar Gonzalez 2024-10-25 12:23:31 -05:00
parent 122c3c7809
commit bfed8a76d8
No known key found for this signature in database
GPG Key ID: 3381A5457F8CCECF
3 changed files with 42 additions and 6 deletions

View File

@ -216,6 +216,7 @@ export type OverlayBackgroundExtensionMessageHandlers = {
getCurrentTabFrameId: ({ sender }: BackgroundSenderParam) => number;
updateSubFrameData: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
triggerSubFrameFocusInRebuild: ({ sender }: BackgroundSenderParam) => void;
shouldRepositionSubFrameInlineMenuOnScroll: ({ sender }: BackgroundSenderParam) => void;
destroyAutofillInlineMenuListeners: ({
message,
sender,

View File

@ -168,6 +168,8 @@ export class OverlayBackground implements OverlayBackgroundInterface {
getCurrentTabFrameId: ({ sender }) => this.getSenderFrameId(sender),
updateSubFrameData: ({ message, sender }) => this.updateSubFrameData(message, sender),
triggerSubFrameFocusInRebuild: ({ sender }) => this.triggerSubFrameFocusInRebuild(sender),
shouldRepositionSubFrameInlineMenuOnScroll: ({ sender }) =>
this.shouldRepositionSubFrameInlineMenuOnScroll(sender),
destroyAutofillInlineMenuListeners: ({ message, sender }) =>
this.triggerDestroyInlineMenuListeners(sender.tab, message.subFrameData.frameId),
collectPageDetailsResponse: ({ message, sender }) => this.storePageDetails(message, sender),
@ -2594,6 +2596,14 @@ export class OverlayBackground implements OverlayBackgroundInterface {
this.repositionInlineMenu$.next(sender);
}
private shouldRepositionSubFrameInlineMenuOnScroll(sender: chrome.runtime.MessageSender) {
if (!this.isFieldCurrentlyFocused || sender.tab.id !== this.focusedFieldData?.tabId) {
return false;
}
return this.focusedFieldData.frameId > 0;
}
/**
* Handles determining if the inline menu should be repositioned or closed, and initiates
* the process of calculating the new position of the inline menu.

View File

@ -1571,14 +1571,35 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
AUTOFILL_OVERLAY_HANDLE_REPOSITION,
);
const eventTargetDoesNotContainFocusedField = (element: Element) =>
typeof element?.contains === "function" && !element.contains(this.mostRecentlyFocusedField);
const eventTargetContainsFocusedField = (eventTarget: Element | Document) => {
if (!eventTarget || !this.mostRecentlyFocusedField) {
return false;
}
const activeElement = (eventTarget as Document).activeElement;
if (activeElement) {
return (
activeElement === this.mostRecentlyFocusedField ||
activeElement.contains(this.mostRecentlyFocusedField)
);
}
if (typeof eventTarget.contains !== "function") {
return false;
}
return (
eventTarget === this.mostRecentlyFocusedField ||
eventTarget.contains(this.mostRecentlyFocusedField)
);
};
const scrollHandler = this.useEventHandlersMemo(
throttle((event) => {
if (eventTargetDoesNotContainFocusedField(event.target as Element)) {
return;
throttle(async (event) => {
if (
eventTargetContainsFocusedField(event.target) ||
(await this.shouldRepositionSubFrameInlineMenuOnScroll())
) {
repositionHandler(event);
}
repositionHandler(event);
}, 50),
AUTOFILL_OVERLAY_HANDLE_SCROLL,
);
@ -1590,6 +1611,10 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
globalThis.addEventListener(EVENTS.RESIZE, repositionHandler);
}
private shouldRepositionSubFrameInlineMenuOnScroll = async () => {
return await this.sendExtensionMessage("shouldRepositionSubFrameInlineMenuOnScroll");
};
/**
* Removes the listeners that facilitate repositioning
* the overlay elements on scroll or resize.