[PM-5189] Fixing a weird side issue that appears when a frame within the page triggers a reposition after the inline menu has been built

This commit is contained in:
Cesar Gonzalez 2024-06-06 13:00:47 -05:00
parent 67db794eda
commit e2c9fa4b59
No known key found for this signature in database
GPG Key ID: 3381A5457F8CCECF
3 changed files with 50 additions and 8 deletions

View File

@ -12,10 +12,11 @@ export type PageDetailsForTab = Record<
>;
export type SubFrameOffsetData = {
frameId?: number;
url?: string;
top: number;
left: number;
url?: string;
frameId?: number;
parentFrameIds?: number[];
} | null;
export type SubFrameOffsetsForTab = Record<
@ -116,6 +117,8 @@ export type OverlayBackgroundExtensionMessageHandlers = {
updateAutofillInlineMenuHidden: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
checkIsAutofillInlineMenuButtonVisible: ({ sender }: BackgroundSenderParam) => void;
checkIsAutofillInlineMenuListVisible: ({ sender }: BackgroundSenderParam) => void;
checkShouldRepositionInlineMenu: ({ sender }: BackgroundSenderParam) => boolean;
getCurrentTabFrameId: ({ sender }: BackgroundSenderParam) => number;
updateSubFrameData: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
rebuildSubFrameOffsets: ({ sender }: BackgroundSenderParam) => void;
collectPageDetailsResponse: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;

View File

@ -88,6 +88,8 @@ export class OverlayBackground implements OverlayBackgroundInterface {
this.checkIsAutofillInlineMenuButtonVisible(sender),
checkIsAutofillInlineMenuListVisible: ({ sender }) =>
this.checkIsAutofillInlineMenuListVisible(sender),
checkShouldRepositionInlineMenu: ({ sender }) => this.checkShouldRepositionInlineMenu(sender),
getCurrentTabFrameId: ({ sender }) => this.getCurrentFrameId(sender),
updateSubFrameData: ({ message, sender }) => this.updateSubFrameData(message, sender),
rebuildSubFrameOffsets: ({ sender }) => this.rebuildSubFrameOffsets(sender),
collectPageDetailsResponse: ({ message, sender }) => this.storePageDetails(message, sender),
@ -256,6 +258,10 @@ export class OverlayBackground implements OverlayBackgroundInterface {
pageDetailsMap.set(sender.frameId, pageDetails);
}
private getCurrentFrameId(sender: chrome.runtime.MessageSender) {
return sender.frameId;
}
/**
* Handles sub frame offset calculations for the given tab and frame id.
* Is used in setting the position of the inline menu list and button.
@ -293,7 +299,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
return;
}
const subFrameData = { url, top: 0, left: 0 };
const subFrameData: SubFrameOffsetData = { url, top: 0, left: 0, parentFrameIds: [] };
let frameDetails = await BrowserApi.getFrameDetails({ tabId, frameId });
while (frameDetails && frameDetails.parentFrameId > -1) {
@ -319,6 +325,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
subFrameData.top += subFrameOffset.top;
subFrameData.left += subFrameOffset.left;
subFrameData.parentFrameIds.push(frameDetails.parentFrameId);
frameDetails = await BrowserApi.getFrameDetails({
tabId,
@ -1005,6 +1012,34 @@ export class OverlayBackground implements OverlayBackgroundInterface {
);
}
private checkShouldRepositionInlineMenu(sender: chrome.runtime.MessageSender): boolean {
if (
!this.focusedFieldData ||
sender.tab.id !== this.focusedFieldData.tabId ||
!this.isFieldCurrentlyFocused
) {
return false;
}
if (this.focusedFieldData.frameId === sender.frameId) {
return true;
}
const subFrameOffsetsForTab = this.subFrameOffsetsForTab[sender.tab.id];
if (!subFrameOffsetsForTab) {
return false;
}
const parentFrameIds = new Set();
subFrameOffsetsForTab.forEach((subFrameOffsetData) =>
subFrameOffsetData.parentFrameIds.forEach((parentFrameId) =>
parentFrameIds.add(parentFrameId),
),
);
return parentFrameIds.has(sender.frameId);
}
/**
* Responds to the content script's request to check if the inline menu ciphers are populated.
* This will return true only if the sender is the focused field's tab and the inline menu

View File

@ -765,17 +765,18 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
globalThis.removeEventListener(EVENTS.RESIZE, this.handleOverlayRepositionEvent);
}
private overlayRepositionTimeout: number | NodeJS.Timeout;
/**
* Handles the resize or scroll events that enact
* repositioning of existing overlay elements.
*/
private handleOverlayRepositionEvent = async () => {
this.rebuildSubFrameOffsets();
if (!(await this.isInlineMenuButtonVisible()) && !(await this.isInlineMenuListVisible())) {
if (!(await this.sendExtensionMessage("checkShouldRepositionInlineMenu"))) {
return;
}
this.rebuildSubFrameOffsets();
this.toggleAutofillInlineMenuHidden(true);
this.clearUserInteractionEventTimeout();
this.userInteractionEventTimeout = setTimeout(this.triggerOverlayRepositionUpdates, 750);
@ -957,6 +958,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
frameId: message.subFrameId,
left: 0,
top: 0,
parentFrameIds: [],
},
},
"*",
@ -968,10 +970,10 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
return;
}
this.calculateSubFramePositioning(event);
void this.calculateSubFramePositioning(event);
};
private calculateSubFramePositioning = (event: MessageEvent) => {
private calculateSubFramePositioning = async (event: MessageEvent) => {
const subFrameData = event.data.subFrameData;
let subFrameOffsets: SubFrameOffsetData;
const iframes = document.querySelectorAll("iframe");
@ -983,9 +985,11 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
subFrameData.url,
subFrameData.frameId,
);
const parentFrameId = await this.sendExtensionMessage("getCurrentTabFrameId");
subFrameData.top += subFrameOffsets.top;
subFrameData.left += subFrameOffsets.left;
subFrameData.parentFrameIds.push(parentFrameId);
break;
}