diff --git a/apps/browser/src/autofill/content/bootstrap-autofill-overlay.ts b/apps/browser/src/autofill/content/bootstrap-autofill-overlay.ts index d98103a068d..32eca6c610a 100644 --- a/apps/browser/src/autofill/content/bootstrap-autofill-overlay.ts +++ b/apps/browser/src/autofill/content/bootstrap-autofill-overlay.ts @@ -1,4 +1,4 @@ -import { InlineMenuElements } from "../overlay/content/inline-menu-elements"; +import { AutofillOverlayInlineMenuElements } from "../overlay/content/autofill-overlay-inline-menu-elements"; import AutofillOverlayContentService from "../services/autofill-overlay-content.service"; import { setupAutofillInitDisconnectAction } from "../utils"; @@ -7,9 +7,9 @@ import AutofillInit from "./autofill-init"; (function (windowContext) { if (!windowContext.bitwardenAutofillInit) { const autofillOverlayContentService = new AutofillOverlayContentService(); - let inlineMenuElements: InlineMenuElements; + let inlineMenuElements: AutofillOverlayInlineMenuElements; if (globalThis.self === globalThis.top) { - inlineMenuElements = new InlineMenuElements(); + inlineMenuElements = new AutofillOverlayInlineMenuElements(); } windowContext.bitwardenAutofillInit = new AutofillInit( autofillOverlayContentService, diff --git a/apps/browser/src/autofill/overlay/content/inline-menu-elements.ts b/apps/browser/src/autofill/overlay/content/autofill-overlay-inline-menu-elements.ts similarity index 99% rename from apps/browser/src/autofill/overlay/content/inline-menu-elements.ts rename to apps/browser/src/autofill/overlay/content/autofill-overlay-inline-menu-elements.ts index 02c1ac9fb75..7144d95369f 100644 --- a/apps/browser/src/autofill/overlay/content/inline-menu-elements.ts +++ b/apps/browser/src/autofill/overlay/content/autofill-overlay-inline-menu-elements.ts @@ -12,7 +12,7 @@ import { import AutofillOverlayButtonIframe from "../iframe-content/autofill-overlay-button-iframe"; import AutofillOverlayListIframe from "../iframe-content/autofill-overlay-list-iframe"; -export class InlineMenuElements implements InlineMenuElementsInterface { +export class AutofillOverlayInlineMenuElements implements InlineMenuElementsInterface { private readonly sendExtensionMessage = sendExtensionMessage; private readonly generateRandomCustomElementName = generateRandomCustomElementName; private readonly setElementStyles = setElementStyles; diff --git a/apps/browser/src/autofill/overlay/pages/shared/autofill-overlay-page-element.spec.ts b/apps/browser/src/autofill/overlay/pages/shared/autofill-overlay-page-element.spec.ts index acdabae9206..ac5d14c1d2c 100644 --- a/apps/browser/src/autofill/overlay/pages/shared/autofill-overlay-page-element.spec.ts +++ b/apps/browser/src/autofill/overlay/pages/shared/autofill-overlay-page-element.spec.ts @@ -12,6 +12,7 @@ describe("AutofillOverlayPageElement", () => { buttonPageTitle: "buttonPageTitle", listPageTitle: "listPageTitle", }; + const portKey = "portKey"; beforeEach(() => { jest.spyOn(globalThis.parent, "postMessage"); @@ -19,6 +20,12 @@ describe("AutofillOverlayPageElement", () => { jest.spyOn(globalThis.document, "addEventListener"); document.body.innerHTML = ""; autofillOverlayPageElement = document.querySelector("autofill-overlay-page-element"); + autofillOverlayPageElement["messageConnectorIframe"] = mock({ + contentWindow: { + postMessage: jest.fn(), + }, + }); + autofillOverlayPageElement["portKey"] = portKey; }); afterEach(() => { @@ -29,6 +36,9 @@ describe("AutofillOverlayPageElement", () => { beforeEach(() => { jest.spyOn(globalThis.document.documentElement, "setAttribute"); jest.spyOn(globalThis.document, "createElement"); + jest + .spyOn(autofillOverlayPageElement as any, "initMessageConnector") + .mockResolvedValue(undefined); }); it("initializes the button overlay page", async () => { @@ -37,7 +47,7 @@ describe("AutofillOverlayPageElement", () => { "https://jest-testing-website.com", translations, "https://jest-testing-website.com/message-connector", - "portKey", + portKey, ); expect(globalThis.document.documentElement.setAttribute).toHaveBeenCalledWith( @@ -52,20 +62,12 @@ describe("AutofillOverlayPageElement", () => { }); describe("postMessageToConnector", () => { - it("skips posting a message to the parent if the message origin in not set", () => { - autofillOverlayPageElement["postMessageToConnector"]({ command: "test" }); - - expect(globalThis.parent.postMessage).not.toHaveBeenCalled(); - }); - it("posts a message to the parent", () => { - autofillOverlayPageElement["messageOrigin"] = "https://jest-testing-website.com"; autofillOverlayPageElement["postMessageToConnector"]({ command: "test" }); - expect(globalThis.parent.postMessage).toHaveBeenCalledWith( - { command: "test" }, - "https://jest-testing-website.com", - ); + expect( + autofillOverlayPageElement["messageConnectorIframe"].contentWindow.postMessage, + ).toHaveBeenCalledWith({ command: "test", portKey }, "*"); }); }); @@ -151,17 +153,15 @@ describe("AutofillOverlayPageElement", () => { }); it("posts a message to the parent when the window is blurred", () => { - autofillOverlayPageElement["messageOrigin"] = "https://jest-testing-website.com"; autofillOverlayPageElement["setupGlobalListeners"]( mock(), ); globalThis.dispatchEvent(new Event("blur")); - expect(globalThis.parent.postMessage).toHaveBeenCalledWith( - { command: "overlayPageBlurred" }, - "https://jest-testing-website.com", - ); + expect( + autofillOverlayPageElement["messageConnectorIframe"].contentWindow.postMessage, + ).toHaveBeenCalledWith({ command: "overlayPageBlurred", portKey }, "*"); }); it("skips redirecting keyboard focus when a KeyDown event triggers and the key is not a `Tab` or `Escape` key", () => { @@ -184,9 +184,11 @@ describe("AutofillOverlayPageElement", () => { new KeyboardEvent("keydown", { code: "Tab", shiftKey: true }), ); - expect(globalThis.parent.postMessage).toHaveBeenCalledWith( - { command: "redirectOverlayFocusOut", direction: "previous" }, - "https://jest-testing-website.com", + expect( + autofillOverlayPageElement["messageConnectorIframe"].contentWindow.postMessage, + ).toHaveBeenCalledWith( + { command: "redirectOverlayFocusOut", direction: "previous", portKey }, + "*", ); }); @@ -198,9 +200,11 @@ describe("AutofillOverlayPageElement", () => { globalThis.document.dispatchEvent(new KeyboardEvent("keydown", { code: "Tab" })); - expect(globalThis.parent.postMessage).toHaveBeenCalledWith( - { command: "redirectOverlayFocusOut", direction: "next" }, - "https://jest-testing-website.com", + expect( + autofillOverlayPageElement["messageConnectorIframe"].contentWindow.postMessage, + ).toHaveBeenCalledWith( + { command: "redirectOverlayFocusOut", direction: "next", portKey }, + "*", ); }); @@ -212,9 +216,11 @@ describe("AutofillOverlayPageElement", () => { globalThis.document.dispatchEvent(new KeyboardEvent("keydown", { code: "Escape" })); - expect(globalThis.parent.postMessage).toHaveBeenCalledWith( - { command: "redirectOverlayFocusOut", direction: "current" }, - "https://jest-testing-website.com", + expect( + autofillOverlayPageElement["messageConnectorIframe"].contentWindow.postMessage, + ).toHaveBeenCalledWith( + { command: "redirectOverlayFocusOut", direction: "current", portKey }, + "*", ); }); }); diff --git a/apps/browser/src/autofill/overlay/pages/shared/autofill-overlay-page-element.ts b/apps/browser/src/autofill/overlay/pages/shared/autofill-overlay-page-element.ts index e2b9ec536c4..edcb378d7e8 100644 --- a/apps/browser/src/autofill/overlay/pages/shared/autofill-overlay-page-element.ts +++ b/apps/browser/src/autofill/overlay/pages/shared/autofill-overlay-page-element.ts @@ -43,28 +43,7 @@ class AutofillOverlayPageElement extends HTMLElement { globalThis.document.documentElement.setAttribute("lang", this.getTranslation("locale")); globalThis.document.head.title = this.getTranslation(`${elementName}PageTitle`); - this.messageConnectorIframe = globalThis.document.createElement("iframe"); - this.messageConnectorIframe.src = messageConnectorUrl; - this.messageConnectorIframe.style.opacity = "0"; - this.messageConnectorIframe.style.position = "absolute"; - this.messageConnectorIframe.style.width = "0"; - this.messageConnectorIframe.style.height = "0"; - this.messageConnectorIframe.style.border = "none"; - this.messageConnectorIframe.style.pointerEvents = "none"; - globalThis.document.body.appendChild(this.messageConnectorIframe); - - await new Promise((resolve) => { - this.messageConnectorIframe.addEventListener(EVENTS.LOAD, () => { - this.postMessageToConnector({ - command: `initAutofillOverlayPort`, - portName: - elementName === "list" - ? AutofillOverlayPort.ListMessageConnector - : AutofillOverlayPort.ButtonMessageConnector, - }); - resolve(); - }); - }); + await this.initMessageConnector(messageConnectorUrl, elementName); this.shadowDom.innerHTML = ""; const linkElement = globalThis.document.createElement("link"); @@ -80,10 +59,6 @@ class AutofillOverlayPageElement extends HTMLElement { * @param message - The message to post */ protected postMessageToConnector(message: AutofillOverlayPageElementWindowMessage) { - if (!this.messageOrigin) { - return; - } - this.messageConnectorIframe.contentWindow.postMessage( { portKey: this.portKey, ...message }, "*", @@ -184,6 +159,31 @@ class AutofillOverlayPageElement extends HTMLElement { private redirectOverlayFocusOutMessage(direction: string) { this.postMessageToConnector({ command: "redirectOverlayFocusOut", direction }); } + + private initMessageConnector(messageConnectorUrl: string, elementName: "button" | "list") { + this.messageConnectorIframe = globalThis.document.createElement("iframe"); + this.messageConnectorIframe.src = messageConnectorUrl; + this.messageConnectorIframe.style.opacity = "0"; + this.messageConnectorIframe.style.position = "absolute"; + this.messageConnectorIframe.style.width = "0"; + this.messageConnectorIframe.style.height = "0"; + this.messageConnectorIframe.style.border = "none"; + this.messageConnectorIframe.style.pointerEvents = "none"; + globalThis.document.body.appendChild(this.messageConnectorIframe); + + return new Promise((resolve) => { + this.messageConnectorIframe.addEventListener(EVENTS.LOAD, () => { + this.postMessageToConnector({ + command: `initAutofillOverlayPort`, + portName: + elementName === "list" + ? AutofillOverlayPort.ListMessageConnector + : AutofillOverlayPort.ButtonMessageConnector, + }); + resolve(); + }); + }); + } } export default AutofillOverlayPageElement;