mirror of
https://github.com/bitwarden/browser
synced 2025-12-18 01:03:35 +00:00
[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:
@@ -12,10 +12,11 @@ export type PageDetailsForTab = Record<
|
|||||||
>;
|
>;
|
||||||
|
|
||||||
export type SubFrameOffsetData = {
|
export type SubFrameOffsetData = {
|
||||||
frameId?: number;
|
|
||||||
url?: string;
|
|
||||||
top: number;
|
top: number;
|
||||||
left: number;
|
left: number;
|
||||||
|
url?: string;
|
||||||
|
frameId?: number;
|
||||||
|
parentFrameIds?: number[];
|
||||||
} | null;
|
} | null;
|
||||||
|
|
||||||
export type SubFrameOffsetsForTab = Record<
|
export type SubFrameOffsetsForTab = Record<
|
||||||
@@ -116,6 +117,8 @@ export type OverlayBackgroundExtensionMessageHandlers = {
|
|||||||
updateAutofillInlineMenuHidden: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
updateAutofillInlineMenuHidden: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
||||||
checkIsAutofillInlineMenuButtonVisible: ({ sender }: BackgroundSenderParam) => void;
|
checkIsAutofillInlineMenuButtonVisible: ({ sender }: BackgroundSenderParam) => void;
|
||||||
checkIsAutofillInlineMenuListVisible: ({ sender }: BackgroundSenderParam) => void;
|
checkIsAutofillInlineMenuListVisible: ({ sender }: BackgroundSenderParam) => void;
|
||||||
|
checkShouldRepositionInlineMenu: ({ sender }: BackgroundSenderParam) => boolean;
|
||||||
|
getCurrentTabFrameId: ({ sender }: BackgroundSenderParam) => number;
|
||||||
updateSubFrameData: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
updateSubFrameData: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
||||||
rebuildSubFrameOffsets: ({ sender }: BackgroundSenderParam) => void;
|
rebuildSubFrameOffsets: ({ sender }: BackgroundSenderParam) => void;
|
||||||
collectPageDetailsResponse: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
collectPageDetailsResponse: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
||||||
|
|||||||
@@ -88,6 +88,8 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
this.checkIsAutofillInlineMenuButtonVisible(sender),
|
this.checkIsAutofillInlineMenuButtonVisible(sender),
|
||||||
checkIsAutofillInlineMenuListVisible: ({ sender }) =>
|
checkIsAutofillInlineMenuListVisible: ({ sender }) =>
|
||||||
this.checkIsAutofillInlineMenuListVisible(sender),
|
this.checkIsAutofillInlineMenuListVisible(sender),
|
||||||
|
checkShouldRepositionInlineMenu: ({ sender }) => this.checkShouldRepositionInlineMenu(sender),
|
||||||
|
getCurrentTabFrameId: ({ sender }) => this.getCurrentFrameId(sender),
|
||||||
updateSubFrameData: ({ message, sender }) => this.updateSubFrameData(message, sender),
|
updateSubFrameData: ({ message, sender }) => this.updateSubFrameData(message, sender),
|
||||||
rebuildSubFrameOffsets: ({ sender }) => this.rebuildSubFrameOffsets(sender),
|
rebuildSubFrameOffsets: ({ sender }) => this.rebuildSubFrameOffsets(sender),
|
||||||
collectPageDetailsResponse: ({ message, sender }) => this.storePageDetails(message, sender),
|
collectPageDetailsResponse: ({ message, sender }) => this.storePageDetails(message, sender),
|
||||||
@@ -256,6 +258,10 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
pageDetailsMap.set(sender.frameId, pageDetails);
|
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.
|
* 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.
|
* Is used in setting the position of the inline menu list and button.
|
||||||
@@ -293,7 +299,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const subFrameData = { url, top: 0, left: 0 };
|
const subFrameData: SubFrameOffsetData = { url, top: 0, left: 0, parentFrameIds: [] };
|
||||||
let frameDetails = await BrowserApi.getFrameDetails({ tabId, frameId });
|
let frameDetails = await BrowserApi.getFrameDetails({ tabId, frameId });
|
||||||
|
|
||||||
while (frameDetails && frameDetails.parentFrameId > -1) {
|
while (frameDetails && frameDetails.parentFrameId > -1) {
|
||||||
@@ -319,6 +325,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
|
|
||||||
subFrameData.top += subFrameOffset.top;
|
subFrameData.top += subFrameOffset.top;
|
||||||
subFrameData.left += subFrameOffset.left;
|
subFrameData.left += subFrameOffset.left;
|
||||||
|
subFrameData.parentFrameIds.push(frameDetails.parentFrameId);
|
||||||
|
|
||||||
frameDetails = await BrowserApi.getFrameDetails({
|
frameDetails = await BrowserApi.getFrameDetails({
|
||||||
tabId,
|
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.
|
* 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
|
* This will return true only if the sender is the focused field's tab and the inline menu
|
||||||
|
|||||||
@@ -765,17 +765,18 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
|||||||
globalThis.removeEventListener(EVENTS.RESIZE, this.handleOverlayRepositionEvent);
|
globalThis.removeEventListener(EVENTS.RESIZE, this.handleOverlayRepositionEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private overlayRepositionTimeout: number | NodeJS.Timeout;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the resize or scroll events that enact
|
* Handles the resize or scroll events that enact
|
||||||
* repositioning of existing overlay elements.
|
* repositioning of existing overlay elements.
|
||||||
*/
|
*/
|
||||||
private handleOverlayRepositionEvent = async () => {
|
private handleOverlayRepositionEvent = async () => {
|
||||||
this.rebuildSubFrameOffsets();
|
if (!(await this.sendExtensionMessage("checkShouldRepositionInlineMenu"))) {
|
||||||
|
|
||||||
if (!(await this.isInlineMenuButtonVisible()) && !(await this.isInlineMenuListVisible())) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.rebuildSubFrameOffsets();
|
||||||
this.toggleAutofillInlineMenuHidden(true);
|
this.toggleAutofillInlineMenuHidden(true);
|
||||||
this.clearUserInteractionEventTimeout();
|
this.clearUserInteractionEventTimeout();
|
||||||
this.userInteractionEventTimeout = setTimeout(this.triggerOverlayRepositionUpdates, 750);
|
this.userInteractionEventTimeout = setTimeout(this.triggerOverlayRepositionUpdates, 750);
|
||||||
@@ -957,6 +958,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
|||||||
frameId: message.subFrameId,
|
frameId: message.subFrameId,
|
||||||
left: 0,
|
left: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
|
parentFrameIds: [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"*",
|
"*",
|
||||||
@@ -968,10 +970,10 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.calculateSubFramePositioning(event);
|
void this.calculateSubFramePositioning(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
private calculateSubFramePositioning = (event: MessageEvent) => {
|
private calculateSubFramePositioning = async (event: MessageEvent) => {
|
||||||
const subFrameData = event.data.subFrameData;
|
const subFrameData = event.data.subFrameData;
|
||||||
let subFrameOffsets: SubFrameOffsetData;
|
let subFrameOffsets: SubFrameOffsetData;
|
||||||
const iframes = document.querySelectorAll("iframe");
|
const iframes = document.querySelectorAll("iframe");
|
||||||
@@ -983,9 +985,11 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
|||||||
subFrameData.url,
|
subFrameData.url,
|
||||||
subFrameData.frameId,
|
subFrameData.frameId,
|
||||||
);
|
);
|
||||||
|
const parentFrameId = await this.sendExtensionMessage("getCurrentTabFrameId");
|
||||||
|
|
||||||
subFrameData.top += subFrameOffsets.top;
|
subFrameData.top += subFrameOffsets.top;
|
||||||
subFrameData.left += subFrameOffsets.left;
|
subFrameData.left += subFrameOffsets.left;
|
||||||
|
subFrameData.parentFrameIds.push(parentFrameId);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user