mirror of
https://github.com/bitwarden/browser
synced 2025-12-19 01:33:33 +00:00
[PM-5189] Implementing a fallback to allow for getting subframe data through post messages if iframe cannot be correctly identified
This commit is contained in:
@@ -12,9 +12,10 @@ type PageDetailsForTab = Record<
|
|||||||
>;
|
>;
|
||||||
|
|
||||||
type SubFrameOffsetData = {
|
type SubFrameOffsetData = {
|
||||||
url: string;
|
url?: string;
|
||||||
top: number;
|
top: number;
|
||||||
left: number;
|
left: number;
|
||||||
|
frameId?: number;
|
||||||
} | null;
|
} | null;
|
||||||
|
|
||||||
type SubFrameOffsetsForTab = Record<
|
type SubFrameOffsetsForTab = Record<
|
||||||
@@ -110,6 +111,7 @@ type OverlayBackgroundExtensionMessageHandlers = {
|
|||||||
updateIsFieldCurrentlyFilling: ({ message }: BackgroundMessageParam) => void;
|
updateIsFieldCurrentlyFilling: ({ message }: BackgroundMessageParam) => void;
|
||||||
checkIsInlineMenuButtonVisible: ({ sender }: BackgroundSenderParam) => void;
|
checkIsInlineMenuButtonVisible: ({ sender }: BackgroundSenderParam) => void;
|
||||||
checkIsInlineMenuListVisible: ({ sender }: BackgroundSenderParam) => void;
|
checkIsInlineMenuListVisible: ({ sender }: BackgroundSenderParam) => void;
|
||||||
|
updateSubFrameData: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
type PortMessageParam = {
|
type PortMessageParam = {
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
(this.isCurrentlyFilling = message.isFieldCurrentlyFilling),
|
(this.isCurrentlyFilling = message.isFieldCurrentlyFilling),
|
||||||
checkIsInlineMenuButtonVisible: ({ sender }) => this.checkIsInlineMenuButtonVisible(sender),
|
checkIsInlineMenuButtonVisible: ({ sender }) => this.checkIsInlineMenuButtonVisible(sender),
|
||||||
checkIsInlineMenuListVisible: ({ sender }) => this.checkIsInlineMenuListVisible(sender),
|
checkIsInlineMenuListVisible: ({ sender }) => this.checkIsInlineMenuListVisible(sender),
|
||||||
|
updateSubFrameData: ({ message, sender }) => this.updateSubFrameData(message, sender),
|
||||||
};
|
};
|
||||||
private readonly overlayButtonPortMessageHandlers: OverlayButtonPortMessageHandlers = {
|
private readonly overlayButtonPortMessageHandlers: OverlayButtonPortMessageHandlers = {
|
||||||
overlayButtonClicked: ({ port }) => this.handleOverlayButtonClicked(port),
|
overlayButtonClicked: ({ port }) => this.handleOverlayButtonClicked(port),
|
||||||
@@ -127,6 +128,13 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateSubFrameData(message: any, sender: chrome.runtime.MessageSender) {
|
||||||
|
const subFrameOffsetsForTab = this.subFrameOffsetsForTab[sender.tab.id];
|
||||||
|
if (subFrameOffsetsForTab) {
|
||||||
|
subFrameOffsetsForTab.set(message.subFrameData.frameId, message.subFrameData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async checkIsInlineMenuListVisible(sender: chrome.runtime.MessageSender) {
|
private async checkIsInlineMenuListVisible(sender: chrome.runtime.MessageSender) {
|
||||||
return await BrowserApi.tabSendMessage(
|
return await BrowserApi.tabSendMessage(
|
||||||
sender.tab,
|
sender.tab,
|
||||||
@@ -277,12 +285,26 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
while (frameDetails.parentFrameId !== -1) {
|
while (frameDetails.parentFrameId !== -1) {
|
||||||
const subFrameOffset: SubFrameOffsetData = await BrowserApi.tabSendMessage(
|
const subFrameOffset: SubFrameOffsetData = await BrowserApi.tabSendMessage(
|
||||||
tab,
|
tab,
|
||||||
{ command: "getSubFrameOffsets", subFrameUrl: frameDetails.url },
|
{
|
||||||
|
command: "getSubFrameOffsets",
|
||||||
|
subFrameUrl: frameDetails.url,
|
||||||
|
subFrameId: frameDetails.documentId,
|
||||||
|
},
|
||||||
{ frameId: frameDetails.parentFrameId },
|
{ frameId: frameDetails.parentFrameId },
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!subFrameOffset) {
|
if (!subFrameOffset) {
|
||||||
subFrameOffsetsForTab.set(frameId, null);
|
subFrameOffsetsForTab.set(frameId, null);
|
||||||
|
void BrowserApi.tabSendMessage(
|
||||||
|
tab,
|
||||||
|
{
|
||||||
|
command: "getSubFrameOffsetsThroughWindowMessaging",
|
||||||
|
subFrameId: frameId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
frameId: frameId,
|
||||||
|
},
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ export type AutofillExtensionMessage = {
|
|||||||
fillScript?: AutofillScript;
|
fillScript?: AutofillScript;
|
||||||
url?: string;
|
url?: string;
|
||||||
subFrameUrl?: string;
|
subFrameUrl?: string;
|
||||||
|
subFrameId?: string;
|
||||||
pageDetailsUrl?: string;
|
pageDetailsUrl?: string;
|
||||||
ciphers?: any;
|
ciphers?: any;
|
||||||
isInlineMenuHidden?: boolean;
|
isInlineMenuHidden?: boolean;
|
||||||
@@ -40,6 +41,7 @@ export type AutofillExtensionMessageHandlers = {
|
|||||||
bgVaultItemRepromptPopoutOpened: () => void;
|
bgVaultItemRepromptPopoutOpened: () => void;
|
||||||
updateAutofillOverlayVisibility: ({ message }: AutofillExtensionMessageParam) => void;
|
updateAutofillOverlayVisibility: ({ message }: AutofillExtensionMessageParam) => void;
|
||||||
getSubFrameOffsets: ({ message }: AutofillExtensionMessageParam) => Promise<SubFrameOffsetData>;
|
getSubFrameOffsets: ({ message }: AutofillExtensionMessageParam) => Promise<SubFrameOffsetData>;
|
||||||
|
getSubFrameOffsetsThroughWindowMessaging: ({ message }: AutofillExtensionMessageParam) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface AutofillInit {
|
export interface AutofillInit {
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ class AutofillInit implements AutofillInitInterface {
|
|||||||
bgVaultItemRepromptPopoutOpened: () => this.blurAndRemoveOverlay(),
|
bgVaultItemRepromptPopoutOpened: () => this.blurAndRemoveOverlay(),
|
||||||
updateAutofillOverlayVisibility: ({ message }) => this.updateAutofillOverlayVisibility(message),
|
updateAutofillOverlayVisibility: ({ message }) => this.updateAutofillOverlayVisibility(message),
|
||||||
getSubFrameOffsets: ({ message }) => this.getSubFrameOffsets(message),
|
getSubFrameOffsets: ({ message }) => this.getSubFrameOffsets(message),
|
||||||
|
getSubFrameOffsetsThroughWindowMessaging: ({ message }) =>
|
||||||
|
this.getSubFrameOffsetsThroughWindowMessaging(message),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,6 +73,45 @@ class AutofillInit implements AutofillInitInterface {
|
|||||||
this.domElementVisibilityService,
|
this.domElementVisibilityService,
|
||||||
this.collectAutofillContentService,
|
this.collectAutofillContentService,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
window.addEventListener("message", (event) => {
|
||||||
|
// if (event.source !== window) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (event.data.command === "calculateSubFramePositioning") {
|
||||||
|
const subFrameData = event.data.subFrameData;
|
||||||
|
let subFrameOffsets: SubFrameOffsetData;
|
||||||
|
const iframes = document.querySelectorAll("iframe");
|
||||||
|
for (let i = 0; i < iframes.length; i++) {
|
||||||
|
if (iframes[i].contentWindow === event.source) {
|
||||||
|
const iframeElement = iframes[i];
|
||||||
|
subFrameOffsets = this.calculateSubFrameOffsets(
|
||||||
|
iframeElement,
|
||||||
|
subFrameData.url,
|
||||||
|
subFrameData.frameId,
|
||||||
|
);
|
||||||
|
|
||||||
|
subFrameData.top += subFrameOffsets.top;
|
||||||
|
subFrameData.left += subFrameOffsets.left;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (globalThis.window.self !== globalThis.window.top) {
|
||||||
|
globalThis.parent.postMessage(
|
||||||
|
{ command: "calculateSubFramePositioning", subFrameData },
|
||||||
|
"*",
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendExtensionMessage("updateSubFrameData", {
|
||||||
|
subFrameData,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -245,14 +286,27 @@ class AutofillInit implements AutofillInitInterface {
|
|||||||
): Promise<SubFrameOffsetData | null> {
|
): Promise<SubFrameOffsetData | null> {
|
||||||
const { subFrameUrl } = message;
|
const { subFrameUrl } = message;
|
||||||
const subFrameUrlWithoutTrailingSlash = subFrameUrl?.replace(/\/$/, "");
|
const subFrameUrlWithoutTrailingSlash = subFrameUrl?.replace(/\/$/, "");
|
||||||
const iframeElement = document.querySelector(
|
|
||||||
|
let iframeElement: HTMLIFrameElement | null = null;
|
||||||
|
const iframeElements = document.querySelectorAll(
|
||||||
`iframe[src="${subFrameUrl}"], iframe[src="${subFrameUrlWithoutTrailingSlash}"]`,
|
`iframe[src="${subFrameUrl}"], iframe[src="${subFrameUrlWithoutTrailingSlash}"]`,
|
||||||
);
|
) as NodeListOf<HTMLIFrameElement>;
|
||||||
|
if (iframeElements.length === 1) {
|
||||||
|
iframeElement = iframeElements[0];
|
||||||
|
}
|
||||||
|
|
||||||
if (!iframeElement) {
|
if (!iframeElement) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return this.calculateSubFrameOffsets(iframeElement, subFrameUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
private calculateSubFrameOffsets(
|
||||||
|
iframeElement: HTMLIFrameElement,
|
||||||
|
subFrameUrl?: string,
|
||||||
|
frameId?: number,
|
||||||
|
): SubFrameOffsetData {
|
||||||
const iframeRect = iframeElement.getBoundingClientRect();
|
const iframeRect = iframeElement.getBoundingClientRect();
|
||||||
const iframeStyles = globalThis.getComputedStyle(iframeElement);
|
const iframeStyles = globalThis.getComputedStyle(iframeElement);
|
||||||
const paddingLeft = parseInt(iframeStyles.getPropertyValue("padding-left"));
|
const paddingLeft = parseInt(iframeStyles.getPropertyValue("padding-left"));
|
||||||
@@ -262,11 +316,27 @@ class AutofillInit implements AutofillInitInterface {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
url: subFrameUrl,
|
url: subFrameUrl,
|
||||||
|
frameId,
|
||||||
top: iframeRect.top + paddingTop + borderWidthTop,
|
top: iframeRect.top + paddingTop + borderWidthTop,
|
||||||
left: iframeRect.left + paddingLeft + borderWidthLeft,
|
left: iframeRect.left + paddingLeft + borderWidthLeft,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getSubFrameOffsetsThroughWindowMessaging(message: any) {
|
||||||
|
globalThis.parent.postMessage(
|
||||||
|
{
|
||||||
|
command: "calculateSubFramePositioning",
|
||||||
|
subFrameData: {
|
||||||
|
url: window.location.href,
|
||||||
|
frameId: message.subFrameId,
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"*",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up the extension message listeners for the content script.
|
* Sets up the extension message listeners for the content script.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user