mirror of
https://github.com/bitwarden/browser.git
synced 2025-01-24 21:41:33 +01:00
[PM-5189] Implementing a set threshold for the maximum depth for which we are willing to calculate sub frame offsets
This commit is contained in:
parent
b1e75ad7b5
commit
b857e4943a
@ -121,6 +121,10 @@ export type OverlayBackgroundExtensionMessageHandlers = {
|
||||
getCurrentTabFrameId: ({ sender }: BackgroundSenderParam) => number;
|
||||
updateSubFrameData: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
||||
rebuildSubFrameOffsets: ({ sender }: BackgroundSenderParam) => void;
|
||||
destroyAutofillInlineMenuListeners: ({
|
||||
message,
|
||||
sender,
|
||||
}: BackgroundOnMessageHandlerParams) => void;
|
||||
collectPageDetailsResponse: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
||||
unlockCompleted: ({ message }: BackgroundMessageParam) => void;
|
||||
addedCipher: () => void;
|
||||
|
@ -25,7 +25,11 @@ import {
|
||||
openAddEditVaultItemPopout,
|
||||
openViewVaultItemPopout,
|
||||
} from "../../vault/popup/utils/vault-popout-window";
|
||||
import { AutofillOverlayElement, AutofillOverlayPort } from "../enums/autofill-overlay.enum";
|
||||
import {
|
||||
AutofillOverlayElement,
|
||||
AutofillOverlayPort,
|
||||
MAX_SUB_FRAME_DEPTH,
|
||||
} from "../enums/autofill-overlay.enum";
|
||||
import { AutofillService } from "../services/abstractions/autofill.service";
|
||||
import { generateRandomChars } from "../utils";
|
||||
|
||||
@ -92,6 +96,8 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
||||
getCurrentTabFrameId: ({ sender }) => this.getSenderFrameId(sender),
|
||||
updateSubFrameData: ({ message, sender }) => this.updateSubFrameData(message, sender),
|
||||
rebuildSubFrameOffsets: ({ sender }) => this.rebuildSubFrameOffsets(sender),
|
||||
destroyAutofillInlineMenuListeners: ({ message, sender }) =>
|
||||
this.triggerDestroyInlineMenuListeners(sender.tab, message.subFrameData.frameId),
|
||||
collectPageDetailsResponse: ({ message, sender }) => this.storePageDetails(message, sender),
|
||||
unlockCompleted: ({ message }) => this.unlockCompleted(message),
|
||||
addedCipher: () => this.updateInlineMenuCiphers(),
|
||||
@ -293,6 +299,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
||||
* @param url - The URL of the sub frame
|
||||
*/
|
||||
private async buildSubFrameOffsets(tab: chrome.tabs.Tab, frameId: number, url: string) {
|
||||
let subFrameDepth = 0;
|
||||
const tabId = tab.id;
|
||||
let subFrameOffsetsForTab = this.subFrameOffsetsForTab[tabId];
|
||||
if (!subFrameOffsetsForTab) {
|
||||
@ -307,7 +314,10 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
||||
const subFrameData: SubFrameOffsetData = { url, top: 0, left: 0, parentFrameIds: [] };
|
||||
let frameDetails = await BrowserApi.getFrameDetails({ tabId, frameId });
|
||||
|
||||
while (frameDetails && frameDetails.parentFrameId > -1) {
|
||||
while (
|
||||
(frameDetails && frameDetails.parentFrameId > -1) ||
|
||||
subFrameDepth > MAX_SUB_FRAME_DEPTH
|
||||
) {
|
||||
const subFrameOffset: SubFrameOffsetData = await BrowserApi.tabSendMessage(
|
||||
tab,
|
||||
{
|
||||
@ -323,7 +333,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
||||
void BrowserApi.tabSendMessage(
|
||||
tab,
|
||||
{ command: "getSubFrameOffsetsFromWindowMessage", subFrameId: frameId },
|
||||
{ frameId: frameId },
|
||||
{ frameId },
|
||||
);
|
||||
return;
|
||||
}
|
||||
@ -336,11 +346,38 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
||||
tabId,
|
||||
frameId: frameDetails.parentFrameId,
|
||||
});
|
||||
subFrameDepth++;
|
||||
}
|
||||
|
||||
if (subFrameDepth > MAX_SUB_FRAME_DEPTH) {
|
||||
subFrameOffsetsForTab.set(frameId, null);
|
||||
this.triggerDestroyInlineMenuListeners(tab, frameId);
|
||||
return;
|
||||
}
|
||||
|
||||
subFrameOffsetsForTab.set(frameId, subFrameData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers a removal and destruction of all
|
||||
*
|
||||
* @param tab - The tab that the sub frame is associated with
|
||||
* @param frameId - The frame ID of the sub frame
|
||||
*/
|
||||
private triggerDestroyInlineMenuListeners(tab: chrome.tabs.Tab, frameId: number) {
|
||||
this.logService.error(
|
||||
"Excessive frame depth encountered, destroying inline menu on field within frame",
|
||||
tab,
|
||||
frameId,
|
||||
);
|
||||
|
||||
void BrowserApi.tabSendMessage(
|
||||
tab,
|
||||
{ command: "destroyAutofillInlineMenuListeners" },
|
||||
{ frameId },
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles rebuilding the sub frame offsets when the tab is repositioned or scrolled.
|
||||
* Will trigger a re-positioning of the inline menu list and button. Note that we
|
||||
|
@ -1,19 +1,19 @@
|
||||
const AutofillOverlayElement = {
|
||||
export const AutofillOverlayElement = {
|
||||
Button: "autofill-inline-menu-button",
|
||||
List: "autofill-inline-menu-list",
|
||||
} as const;
|
||||
|
||||
const AutofillOverlayPort = {
|
||||
export const AutofillOverlayPort = {
|
||||
Button: "autofill-inline-menu-button-port",
|
||||
ButtonMessageConnector: "autofill-inline-menu-button-message-connector",
|
||||
List: "autofill-inline-menu-list-port",
|
||||
ListMessageConnector: "autofill-inline-menu-list-message-connector",
|
||||
} as const;
|
||||
|
||||
const RedirectFocusDirection = {
|
||||
export const RedirectFocusDirection = {
|
||||
Current: "current",
|
||||
Previous: "previous",
|
||||
Next: "next",
|
||||
} as const;
|
||||
|
||||
export { AutofillOverlayElement, AutofillOverlayPort, RedirectFocusDirection };
|
||||
export const MAX_SUB_FRAME_DEPTH = 10;
|
||||
|
@ -11,6 +11,10 @@ export type OpenAutofillInlineMenuOptions = {
|
||||
authStatus?: AuthenticationStatus;
|
||||
};
|
||||
|
||||
export type SubFrameDataFromWindowMessage = SubFrameOffsetData & {
|
||||
subFrameDepth: number;
|
||||
};
|
||||
|
||||
export type AutofillOverlayContentExtensionMessageHandlers = {
|
||||
[key: string]: CallableFunction;
|
||||
openAutofillInlineMenu: ({ message }: AutofillExtensionMessageParam) => void;
|
||||
@ -24,6 +28,7 @@ export type AutofillOverlayContentExtensionMessageHandlers = {
|
||||
getSubFrameOffsets: ({ message }: AutofillExtensionMessageParam) => Promise<SubFrameOffsetData>;
|
||||
getSubFrameOffsetsFromWindowMessage: ({ message }: AutofillExtensionMessageParam) => void;
|
||||
checkMostRecentlyFocusedFieldHasValue: () => boolean;
|
||||
destroyAutofillInlineMenuListeners: () => void;
|
||||
};
|
||||
|
||||
export interface AutofillOverlayContentService {
|
||||
|
@ -10,7 +10,11 @@ import {
|
||||
SubFrameOffsetData,
|
||||
} from "../background/abstractions/overlay.background";
|
||||
import { AutofillExtensionMessage } from "../content/abstractions/autofill-init";
|
||||
import { AutofillOverlayElement, RedirectFocusDirection } from "../enums/autofill-overlay.enum";
|
||||
import {
|
||||
AutofillOverlayElement,
|
||||
MAX_SUB_FRAME_DEPTH,
|
||||
RedirectFocusDirection,
|
||||
} from "../enums/autofill-overlay.enum";
|
||||
import AutofillField from "../models/autofill-field";
|
||||
import { ElementWithOpId, FillableFormFieldElement, FormFieldElement } from "../types";
|
||||
import { elementIsFillableFormField, getAttributeBoolean, sendExtensionMessage } from "../utils";
|
||||
@ -19,6 +23,7 @@ import {
|
||||
AutofillOverlayContentExtensionMessageHandlers,
|
||||
AutofillOverlayContentService as AutofillOverlayContentServiceInterface,
|
||||
OpenAutofillInlineMenuOptions,
|
||||
SubFrameDataFromWindowMessage,
|
||||
} from "./abstractions/autofill-overlay-content.service";
|
||||
import { AutoFillConstants } from "./autofill-constants";
|
||||
|
||||
@ -54,6 +59,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
||||
getSubFrameOffsetsFromWindowMessage: ({ message }) =>
|
||||
this.getSubFrameOffsetsFromWindowMessage(message),
|
||||
checkMostRecentlyFocusedFieldHasValue: () => this.mostRecentlyFocusedFieldHasValue(),
|
||||
destroyAutofillInlineMenuListeners: () => this.destroy(),
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1025,7 +1031,8 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
||||
left: 0,
|
||||
top: 0,
|
||||
parentFrameIds: [],
|
||||
},
|
||||
subFrameDepth: 0,
|
||||
} as SubFrameDataFromWindowMessage,
|
||||
},
|
||||
"*",
|
||||
);
|
||||
@ -1050,7 +1057,14 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
||||
* @param event - The message event.
|
||||
*/
|
||||
private calculateSubFramePositioning = async (event: MessageEvent) => {
|
||||
const subFrameData = event.data.subFrameData;
|
||||
const subFrameData: SubFrameDataFromWindowMessage = event.data.subFrameData;
|
||||
|
||||
subFrameData.subFrameDepth++;
|
||||
if (subFrameData.subFrameDepth > MAX_SUB_FRAME_DEPTH) {
|
||||
void this.sendExtensionMessage("destroyAutofillInlineMenuListeners", { subFrameData });
|
||||
return;
|
||||
}
|
||||
|
||||
let subFrameOffsets: SubFrameOffsetData;
|
||||
const iframes = globalThis.document.querySelectorAll("iframe");
|
||||
for (let i = 0; i < iframes.length; i++) {
|
||||
@ -1079,9 +1093,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
||||
return;
|
||||
}
|
||||
|
||||
void this.sendExtensionMessage("updateSubFrameData", {
|
||||
subFrameData,
|
||||
});
|
||||
void this.sendExtensionMessage("updateSubFrameData", { subFrameData });
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user