mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 00:33:44 +00: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:
@@ -121,6 +121,10 @@ export type OverlayBackgroundExtensionMessageHandlers = {
|
|||||||
getCurrentTabFrameId: ({ sender }: BackgroundSenderParam) => number;
|
getCurrentTabFrameId: ({ sender }: BackgroundSenderParam) => number;
|
||||||
updateSubFrameData: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
updateSubFrameData: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
||||||
rebuildSubFrameOffsets: ({ sender }: BackgroundSenderParam) => void;
|
rebuildSubFrameOffsets: ({ sender }: BackgroundSenderParam) => void;
|
||||||
|
destroyAutofillInlineMenuListeners: ({
|
||||||
|
message,
|
||||||
|
sender,
|
||||||
|
}: BackgroundOnMessageHandlerParams) => void;
|
||||||
collectPageDetailsResponse: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
collectPageDetailsResponse: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
||||||
unlockCompleted: ({ message }: BackgroundMessageParam) => void;
|
unlockCompleted: ({ message }: BackgroundMessageParam) => void;
|
||||||
addedCipher: () => void;
|
addedCipher: () => void;
|
||||||
|
|||||||
@@ -25,7 +25,11 @@ import {
|
|||||||
openAddEditVaultItemPopout,
|
openAddEditVaultItemPopout,
|
||||||
openViewVaultItemPopout,
|
openViewVaultItemPopout,
|
||||||
} from "../../vault/popup/utils/vault-popout-window";
|
} 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 { AutofillService } from "../services/abstractions/autofill.service";
|
||||||
import { generateRandomChars } from "../utils";
|
import { generateRandomChars } from "../utils";
|
||||||
|
|
||||||
@@ -92,6 +96,8 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
getCurrentTabFrameId: ({ sender }) => this.getSenderFrameId(sender),
|
getCurrentTabFrameId: ({ sender }) => this.getSenderFrameId(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),
|
||||||
|
destroyAutofillInlineMenuListeners: ({ message, sender }) =>
|
||||||
|
this.triggerDestroyInlineMenuListeners(sender.tab, message.subFrameData.frameId),
|
||||||
collectPageDetailsResponse: ({ message, sender }) => this.storePageDetails(message, sender),
|
collectPageDetailsResponse: ({ message, sender }) => this.storePageDetails(message, sender),
|
||||||
unlockCompleted: ({ message }) => this.unlockCompleted(message),
|
unlockCompleted: ({ message }) => this.unlockCompleted(message),
|
||||||
addedCipher: () => this.updateInlineMenuCiphers(),
|
addedCipher: () => this.updateInlineMenuCiphers(),
|
||||||
@@ -293,6 +299,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
* @param url - The URL of the sub frame
|
* @param url - The URL of the sub frame
|
||||||
*/
|
*/
|
||||||
private async buildSubFrameOffsets(tab: chrome.tabs.Tab, frameId: number, url: string) {
|
private async buildSubFrameOffsets(tab: chrome.tabs.Tab, frameId: number, url: string) {
|
||||||
|
let subFrameDepth = 0;
|
||||||
const tabId = tab.id;
|
const tabId = tab.id;
|
||||||
let subFrameOffsetsForTab = this.subFrameOffsetsForTab[tabId];
|
let subFrameOffsetsForTab = this.subFrameOffsetsForTab[tabId];
|
||||||
if (!subFrameOffsetsForTab) {
|
if (!subFrameOffsetsForTab) {
|
||||||
@@ -307,7 +314,10 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
const subFrameData: SubFrameOffsetData = { url, top: 0, left: 0, parentFrameIds: [] };
|
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) ||
|
||||||
|
subFrameDepth > MAX_SUB_FRAME_DEPTH
|
||||||
|
) {
|
||||||
const subFrameOffset: SubFrameOffsetData = await BrowserApi.tabSendMessage(
|
const subFrameOffset: SubFrameOffsetData = await BrowserApi.tabSendMessage(
|
||||||
tab,
|
tab,
|
||||||
{
|
{
|
||||||
@@ -323,7 +333,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
void BrowserApi.tabSendMessage(
|
void BrowserApi.tabSendMessage(
|
||||||
tab,
|
tab,
|
||||||
{ command: "getSubFrameOffsetsFromWindowMessage", subFrameId: frameId },
|
{ command: "getSubFrameOffsetsFromWindowMessage", subFrameId: frameId },
|
||||||
{ frameId: frameId },
|
{ frameId },
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -336,11 +346,38 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
tabId,
|
tabId,
|
||||||
frameId: frameDetails.parentFrameId,
|
frameId: frameDetails.parentFrameId,
|
||||||
});
|
});
|
||||||
|
subFrameDepth++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subFrameDepth > MAX_SUB_FRAME_DEPTH) {
|
||||||
|
subFrameOffsetsForTab.set(frameId, null);
|
||||||
|
this.triggerDestroyInlineMenuListeners(tab, frameId);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
subFrameOffsetsForTab.set(frameId, subFrameData);
|
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.
|
* 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
|
* 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",
|
Button: "autofill-inline-menu-button",
|
||||||
List: "autofill-inline-menu-list",
|
List: "autofill-inline-menu-list",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const AutofillOverlayPort = {
|
export const AutofillOverlayPort = {
|
||||||
Button: "autofill-inline-menu-button-port",
|
Button: "autofill-inline-menu-button-port",
|
||||||
ButtonMessageConnector: "autofill-inline-menu-button-message-connector",
|
ButtonMessageConnector: "autofill-inline-menu-button-message-connector",
|
||||||
List: "autofill-inline-menu-list-port",
|
List: "autofill-inline-menu-list-port",
|
||||||
ListMessageConnector: "autofill-inline-menu-list-message-connector",
|
ListMessageConnector: "autofill-inline-menu-list-message-connector",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const RedirectFocusDirection = {
|
export const RedirectFocusDirection = {
|
||||||
Current: "current",
|
Current: "current",
|
||||||
Previous: "previous",
|
Previous: "previous",
|
||||||
Next: "next",
|
Next: "next",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export { AutofillOverlayElement, AutofillOverlayPort, RedirectFocusDirection };
|
export const MAX_SUB_FRAME_DEPTH = 10;
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ export type OpenAutofillInlineMenuOptions = {
|
|||||||
authStatus?: AuthenticationStatus;
|
authStatus?: AuthenticationStatus;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type SubFrameDataFromWindowMessage = SubFrameOffsetData & {
|
||||||
|
subFrameDepth: number;
|
||||||
|
};
|
||||||
|
|
||||||
export type AutofillOverlayContentExtensionMessageHandlers = {
|
export type AutofillOverlayContentExtensionMessageHandlers = {
|
||||||
[key: string]: CallableFunction;
|
[key: string]: CallableFunction;
|
||||||
openAutofillInlineMenu: ({ message }: AutofillExtensionMessageParam) => void;
|
openAutofillInlineMenu: ({ message }: AutofillExtensionMessageParam) => void;
|
||||||
@@ -24,6 +28,7 @@ export type AutofillOverlayContentExtensionMessageHandlers = {
|
|||||||
getSubFrameOffsets: ({ message }: AutofillExtensionMessageParam) => Promise<SubFrameOffsetData>;
|
getSubFrameOffsets: ({ message }: AutofillExtensionMessageParam) => Promise<SubFrameOffsetData>;
|
||||||
getSubFrameOffsetsFromWindowMessage: ({ message }: AutofillExtensionMessageParam) => void;
|
getSubFrameOffsetsFromWindowMessage: ({ message }: AutofillExtensionMessageParam) => void;
|
||||||
checkMostRecentlyFocusedFieldHasValue: () => boolean;
|
checkMostRecentlyFocusedFieldHasValue: () => boolean;
|
||||||
|
destroyAutofillInlineMenuListeners: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface AutofillOverlayContentService {
|
export interface AutofillOverlayContentService {
|
||||||
|
|||||||
@@ -10,7 +10,11 @@ import {
|
|||||||
SubFrameOffsetData,
|
SubFrameOffsetData,
|
||||||
} from "../background/abstractions/overlay.background";
|
} from "../background/abstractions/overlay.background";
|
||||||
import { AutofillExtensionMessage } from "../content/abstractions/autofill-init";
|
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 AutofillField from "../models/autofill-field";
|
||||||
import { ElementWithOpId, FillableFormFieldElement, FormFieldElement } from "../types";
|
import { ElementWithOpId, FillableFormFieldElement, FormFieldElement } from "../types";
|
||||||
import { elementIsFillableFormField, getAttributeBoolean, sendExtensionMessage } from "../utils";
|
import { elementIsFillableFormField, getAttributeBoolean, sendExtensionMessage } from "../utils";
|
||||||
@@ -19,6 +23,7 @@ import {
|
|||||||
AutofillOverlayContentExtensionMessageHandlers,
|
AutofillOverlayContentExtensionMessageHandlers,
|
||||||
AutofillOverlayContentService as AutofillOverlayContentServiceInterface,
|
AutofillOverlayContentService as AutofillOverlayContentServiceInterface,
|
||||||
OpenAutofillInlineMenuOptions,
|
OpenAutofillInlineMenuOptions,
|
||||||
|
SubFrameDataFromWindowMessage,
|
||||||
} from "./abstractions/autofill-overlay-content.service";
|
} from "./abstractions/autofill-overlay-content.service";
|
||||||
import { AutoFillConstants } from "./autofill-constants";
|
import { AutoFillConstants } from "./autofill-constants";
|
||||||
|
|
||||||
@@ -54,6 +59,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
|||||||
getSubFrameOffsetsFromWindowMessage: ({ message }) =>
|
getSubFrameOffsetsFromWindowMessage: ({ message }) =>
|
||||||
this.getSubFrameOffsetsFromWindowMessage(message),
|
this.getSubFrameOffsetsFromWindowMessage(message),
|
||||||
checkMostRecentlyFocusedFieldHasValue: () => this.mostRecentlyFocusedFieldHasValue(),
|
checkMostRecentlyFocusedFieldHasValue: () => this.mostRecentlyFocusedFieldHasValue(),
|
||||||
|
destroyAutofillInlineMenuListeners: () => this.destroy(),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1025,7 +1031,8 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
|||||||
left: 0,
|
left: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
parentFrameIds: [],
|
parentFrameIds: [],
|
||||||
},
|
subFrameDepth: 0,
|
||||||
|
} as SubFrameDataFromWindowMessage,
|
||||||
},
|
},
|
||||||
"*",
|
"*",
|
||||||
);
|
);
|
||||||
@@ -1050,7 +1057,14 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
|||||||
* @param event - The message event.
|
* @param event - The message event.
|
||||||
*/
|
*/
|
||||||
private calculateSubFramePositioning = async (event: MessageEvent) => {
|
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;
|
let subFrameOffsets: SubFrameOffsetData;
|
||||||
const iframes = globalThis.document.querySelectorAll("iframe");
|
const iframes = globalThis.document.querySelectorAll("iframe");
|
||||||
for (let i = 0; i < iframes.length; i++) {
|
for (let i = 0; i < iframes.length; i++) {
|
||||||
@@ -1079,9 +1093,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void this.sendExtensionMessage("updateSubFrameData", {
|
void this.sendExtensionMessage("updateSubFrameData", { subFrameData });
|
||||||
subFrameData,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user