1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-19 09:43:23 +00:00

[PM-5189] Implementing methodology for gathering iframe rects within background script

This commit is contained in:
Cesar Gonzalez
2024-03-19 17:57:54 -05:00
parent bd68fff840
commit a3b12581f7
5 changed files with 80 additions and 18 deletions

View File

@@ -15,7 +15,7 @@ type SubFrameOffsetData = {
url: string;
top: number;
left: number;
};
} | null;
type SubFrameOffsetsForTab = Record<
chrome.runtime.MessageSender["tab"]["id"],

View File

@@ -42,6 +42,7 @@ import {
WebsiteIconData,
PageDetailsForTab,
SubFrameOffsetsForTab,
SubFrameOffsetData,
} from "./abstractions/overlay.background";
class OverlayBackground implements OverlayBackgroundInterface {
@@ -112,14 +113,17 @@ class OverlayBackground implements OverlayBackgroundInterface {
* @param tabId - Used to reference the page details of a specific tab
*/
removePageDetails(tabId: number) {
if (!this.pageDetailsForTab[tabId]) {
return;
}
if (this.pageDetailsForTab[tabId]) {
this.pageDetailsForTab[tabId].clear();
delete this.pageDetailsForTab[tabId];
}
if (this.subFrameOffsetsForTab[tabId]) {
this.subFrameOffsetsForTab[tabId].clear();
delete this.subFrameOffsetsForTab[tabId];
}
}
/**
* Sets up the extension message listeners and gets the settings for the
* overlay's visibility and the user's authentication status.
@@ -212,7 +216,6 @@ class OverlayBackground implements OverlayBackgroundInterface {
};
if (pageDetails.frameId !== 0 && pageDetails.details.fields.length) {
// NOT SURE I WANT THIS
void this.buildSubFrameOffset(pageDetails);
}
@@ -226,13 +229,42 @@ class OverlayBackground implements OverlayBackgroundInterface {
}
private async buildSubFrameOffset({ tab, frameId, details }: PageDetail) {
const frameDetails = await BrowserApi.getFrameDetails({
tabId: tab.id,
frameId,
});
const tabId = tab.id;
let subFrameOffsetsForTab = this.subFrameOffsetsForTab[tabId];
if (!subFrameOffsetsForTab) {
this.subFrameOffsetsForTab[tabId] = new Map();
subFrameOffsetsForTab = this.subFrameOffsetsForTab[tabId];
}
// eslint-disable-next-line
console.log(frameDetails);
if (subFrameOffsetsForTab.get(frameId)) {
return;
}
const subFrameData = { url: details.url, top: 0, left: 0 };
let frameDetails = await BrowserApi.getFrameDetails({ tabId, frameId });
while (frameDetails.parentFrameId !== -1) {
const subFrameOffset: SubFrameOffsetData = await BrowserApi.tabSendMessage(
tab,
{ command: "getSubFrameOffsets", subFrameUrl: frameDetails.url },
{ frameId: frameDetails.parentFrameId },
);
if (!subFrameOffset) {
subFrameOffsetsForTab.set(frameId, null);
return;
}
subFrameData.top += subFrameOffset.top;
subFrameData.left += subFrameOffset.left;
frameDetails = await BrowserApi.getFrameDetails({
tabId,
frameId: frameDetails.parentFrameId,
});
}
subFrameOffsetsForTab.set(frameId, subFrameData);
}
/**

View File

@@ -1,5 +1,6 @@
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
import { SubFrameOffsetData } from "../../background/abstractions/overlay.background";
import AutofillScript from "../../models/autofill-script";
type AutofillExtensionMessage = {
@@ -8,6 +9,7 @@ type AutofillExtensionMessage = {
sender?: string;
fillScript?: AutofillScript;
url?: string;
subFrameUrl?: string;
pageDetailsUrl?: string;
ciphers?: any;
data?: {
@@ -36,6 +38,7 @@ type AutofillExtensionMessageHandlers = {
bgUnlockPopoutOpened: () => void;
bgVaultItemRepromptPopoutOpened: () => void;
updateAutofillOverlayVisibility: ({ message }: AutofillExtensionMessageParam) => void;
getSubFrameOffsets: ({ message }: AutofillExtensionMessageParam) => Promise<SubFrameOffsetData>;
};
interface AutofillInit {

View File

@@ -1,3 +1,4 @@
import { SubFrameOffsetData } from "../background/abstractions/overlay.background";
import AutofillPageDetails from "../models/autofill-page-details";
import { AutofillOverlayContentService } from "../services/abstractions/autofill-overlay-content.service";
import CollectAutofillContentService from "../services/collect-autofill-content.service";
@@ -28,7 +29,7 @@ class AutofillInit implements AutofillInitInterface {
bgUnlockPopoutOpened: () => this.blurAndRemoveOverlay(),
bgVaultItemRepromptPopoutOpened: () => this.blurAndRemoveOverlay(),
updateAutofillOverlayVisibility: ({ message }) => this.updateAutofillOverlayVisibility(message),
getSubFrameOffsets: () => this.getSubFrameOffsets(),
getSubFrameOffsets: ({ message }) => this.getSubFrameOffsets(message),
};
/**
@@ -250,7 +251,33 @@ class AutofillInit implements AutofillInitInterface {
this.autofillOverlayContentService.autofillOverlayVisibility = data?.autofillOverlayVisibility;
}
private getSubFrameOffsets() {}
private async getSubFrameOffsets(
message: AutofillExtensionMessage,
): Promise<SubFrameOffsetData | null> {
const { subFrameUrl } = message;
const subFrameUrlWithoutTrailingSlash = subFrameUrl?.replace(/\/$/, "");
// query iframe based on src attribute
const iframeElement = document.querySelector(
`iframe[src^="${subFrameUrlWithoutTrailingSlash}"]`,
);
if (!iframeElement) {
return null;
}
const iframeRect = iframeElement.getBoundingClientRect();
const iframeStyles = globalThis.getComputedStyle(iframeElement);
const paddingLeft = parseInt(iframeStyles.getPropertyValue("padding-left"));
const paddingTop = parseInt(iframeStyles.getPropertyValue("padding-top"));
const borderWidthLeft = parseInt(iframeStyles.getPropertyValue("border-left-width"));
const borderWidthTop = parseInt(iframeStyles.getPropertyValue("border-top-width"));
return {
url: subFrameUrl,
top: iframeRect.top + paddingTop + borderWidthTop,
left: iframeRect.left + paddingLeft + borderWidthLeft,
};
}
/**
* Sets up the extension message listeners for the content script.

View File

@@ -178,17 +178,17 @@ export class BrowserApi {
tab: chrome.tabs.Tab,
obj: T,
options: chrome.tabs.MessageSendOptions = null,
): Promise<void> {
): Promise<any> {
if (!tab || !tab.id) {
return;
}
return new Promise<void>((resolve) => {
chrome.tabs.sendMessage(tab.id, obj, options, () => {
return new Promise<any>((resolve) => {
chrome.tabs.sendMessage(tab.id, obj, options, (response) => {
if (chrome.runtime.lastError) {
// Some error happened
}
resolve();
resolve(response);
});
});
}