diff --git a/apps/browser/src/autofill/background/overlay.background.ts b/apps/browser/src/autofill/background/overlay.background.ts index 094a005908..1248dec09e 100644 --- a/apps/browser/src/autofill/background/overlay.background.ts +++ b/apps/browser/src/autofill/background/overlay.background.ts @@ -286,12 +286,7 @@ export class OverlayBackground implements OverlayBackgroundInterface { }; if (pageDetails.frameId !== 0 && pageDetails.details.fields.length) { - void this.buildSubFrameOffsets( - pageDetails.tab, - pageDetails.frameId, - pageDetails.details.url, - sender, - ); + void this.buildSubFrameOffsets(pageDetails.tab, pageDetails.frameId, pageDetails.details.url); void BrowserApi.tabSendMessage(pageDetails.tab, { command: "setupRebuildSubFrameOffsetsListeners", }); @@ -341,13 +336,13 @@ export class OverlayBackground implements OverlayBackgroundInterface { * @param tab - The tab that the sub frame is associated with * @param frameId - The frame ID of the sub frame * @param url - The URL of the sub frame - * @param sender - The sender of the message + * @param forceRebuild - Identifies whether the sub frame offsets should be rebuilt */ private async buildSubFrameOffsets( tab: chrome.tabs.Tab, frameId: number, url: string, - sender: chrome.runtime.MessageSender, + forceRebuild: boolean = false, ) { let subFrameDepth = 0; const tabId = tab.id; @@ -357,7 +352,7 @@ export class OverlayBackground implements OverlayBackgroundInterface { subFrameOffsetsForTab = this.subFrameOffsetsForTab[tabId]; } - if (subFrameOffsetsForTab.get(frameId)) { + if (!forceRebuild && subFrameOffsetsForTab.get(frameId)) { return; } @@ -438,8 +433,7 @@ export class OverlayBackground implements OverlayBackgroundInterface { if (subFrameOffsetsForTab) { const tabFrameIds = Array.from(subFrameOffsetsForTab.keys()); for (const frameId of tabFrameIds) { - subFrameOffsetsForTab.delete(frameId); - await this.buildSubFrameOffsets(sender.tab, frameId, sender.url, sender); + await this.buildSubFrameOffsets(sender.tab, frameId, sender.url, true); } } } @@ -664,6 +658,11 @@ export class OverlayBackground implements OverlayBackgroundInterface { let subFrameOffsets: SubFrameOffsetData; if (subFrameOffsetsForTab) { subFrameOffsets = subFrameOffsetsForTab.get(this.focusedFieldData.frameId); + if (subFrameOffsets === null) { + this.cancelUpdateInlineMenuPositionSubject.next(); + this.startUpdateInlineMenuPositionSubject.next(sender); + return; + } } if (overlayElement === AutofillOverlayElement.Button) { diff --git a/apps/browser/src/autofill/background/tabs.background.spec.ts b/apps/browser/src/autofill/background/tabs.background.spec.ts index 1b48aa3f53..39480648ba 100644 --- a/apps/browser/src/autofill/background/tabs.background.spec.ts +++ b/apps/browser/src/autofill/background/tabs.background.spec.ts @@ -154,18 +154,6 @@ describe("TabsBackground", () => { }); }); - it("removes the cached page details from the overlay background if the tab status is `loading`", () => { - triggerTabOnUpdatedEvent(focusedWindowId, { status: "loading" }, tab); - - expect(overlayBackground.removePageDetails).toHaveBeenCalledWith(focusedWindowId); - }); - - it("removes the cached page details from the overlay background if the tab status is `unloaded`", () => { - triggerTabOnUpdatedEvent(focusedWindowId, { status: "unloaded" }, tab); - - expect(overlayBackground.removePageDetails).toHaveBeenCalledWith(focusedWindowId); - }); - it("skips updating the current tab data the focusedWindowId is set to a value less than zero", async () => { tab.windowId = -1; triggerTabOnUpdatedEvent(focusedWindowId, { status: "loading" }, tab); diff --git a/apps/browser/src/autofill/services/autofill-overlay-content.service.ts b/apps/browser/src/autofill/services/autofill-overlay-content.service.ts index 397cd2f8db..2d284563ce 100644 --- a/apps/browser/src/autofill/services/autofill-overlay-content.service.ts +++ b/apps/browser/src/autofill/services/autofill-overlay-content.service.ts @@ -844,14 +844,26 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ message: AutofillExtensionMessage, ): Promise { const { subFrameUrl } = message; - const subFrameUrlWithoutTrailingSlash = subFrameUrl?.replace(/\/$/, ""); + + const subFrameUrlVariations = this.getSubFrameUrlVariations(subFrameUrl); + if (!subFrameUrlVariations) { + return null; + } let iframeElement: HTMLIFrameElement | null = null; - const iframeElements = globalThis.document.querySelectorAll( - `iframe[src="${subFrameUrl}"], iframe[src="${subFrameUrlWithoutTrailingSlash}"]`, - ) as NodeListOf; - if (iframeElements.length === 1) { - iframeElement = iframeElements[0]; + const iframeElements = globalThis.document.getElementsByTagName("iframe"); + + for (let iframeIndex = 0; iframeIndex < iframeElements.length; iframeIndex++) { + const iframe = iframeElements[iframeIndex]; + if (!subFrameUrlVariations.has(iframe.src)) { + continue; + } + + if (iframeElement) { + return null; + } + + iframeElement = iframe; } if (!iframeElement) { @@ -861,6 +873,50 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ return this.calculateSubFrameOffsets(iframeElement, subFrameUrl); } + private getSubFrameUrlVariations(subFrameUrl: string) { + try { + const url = new URL(subFrameUrl, globalThis.location.href); + const pathAndHash = url.pathname + url.hash; + const pathAndSearch = url.pathname + url.search; + const pathSearchAndHash = pathAndSearch + url.hash; + const pathNameWithoutTrailingSlash = url.pathname.replace(/\/$/, ""); + const pathWithoutTrailingSlashAndHash = pathNameWithoutTrailingSlash + url.hash; + const pathWithoutTrailingSlashAndSearch = pathNameWithoutTrailingSlash + url.search; + const pathWithoutTrailingSlashSearchAndHash = pathWithoutTrailingSlashAndSearch + url.hash; + + return new Set([ + url.href, + url.href.replace(/\/$/, ""), + url.pathname, + pathAndHash, + pathAndSearch, + pathSearchAndHash, + pathNameWithoutTrailingSlash, + pathWithoutTrailingSlashAndHash, + pathWithoutTrailingSlashAndSearch, + pathWithoutTrailingSlashSearchAndHash, + url.hostname + url.pathname, + url.hostname + pathAndHash, + url.hostname + pathAndSearch, + url.hostname + pathSearchAndHash, + url.hostname + pathNameWithoutTrailingSlash, + url.hostname + pathWithoutTrailingSlashAndHash, + url.hostname + pathWithoutTrailingSlashAndSearch, + url.hostname + pathWithoutTrailingSlashSearchAndHash, + url.origin + url.pathname, + url.origin + pathAndHash, + url.origin + pathAndSearch, + url.origin + pathSearchAndHash, + url.origin + pathNameWithoutTrailingSlash, + url.origin + pathWithoutTrailingSlashAndHash, + url.origin + pathWithoutTrailingSlashAndSearch, + url.origin + pathWithoutTrailingSlashSearchAndHash, + ]); + } catch (_error) { + return null; + } + } + /** * Posts a message to the parent frame to calculate the sub frame offset of the current frame. *