mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-11 10:10:25 +01:00
[PM-11474] Rework injection of delayed passkey script to address identified bugs (#10830)
* [PM-11474] Delay cleanup of injected passkey script * [PM-11474] Incorporating changes to ensure passkeys function within Safari script effectively * [PM-11474] Fixing jest tests * [PM-11474] Fixing jest tests
This commit is contained in:
parent
55ffe9913d
commit
e594059865
@ -4,12 +4,21 @@ describe("FIDO2 page-script for manifest v2", () => {
|
|||||||
let createdScriptElement: HTMLScriptElement;
|
let createdScriptElement: HTMLScriptElement;
|
||||||
jest.spyOn(window.document, "createElement");
|
jest.spyOn(window.document, "createElement");
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
Object.defineProperty(window.document, "contentType", { value: "text/html", writable: true });
|
Object.defineProperty(window.document, "contentType", { value: "text/html", writable: true });
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
|
jest.clearAllTimers();
|
||||||
jest.resetModules();
|
jest.resetModules();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
jest.useRealTimers();
|
||||||
|
});
|
||||||
|
|
||||||
it("skips appending the `page-script.js` file if the document contentType is not `text/html`", () => {
|
it("skips appending the `page-script.js` file if the document contentType is not `text/html`", () => {
|
||||||
Object.defineProperty(window.document, "contentType", { value: "text/plain", writable: true });
|
Object.defineProperty(window.document, "contentType", { value: "text/plain", writable: true });
|
||||||
|
|
||||||
@ -19,7 +28,7 @@ describe("FIDO2 page-script for manifest v2", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("appends the `page-script.js` file to the document head when the contentType is `text/html`", () => {
|
it("appends the `page-script.js` file to the document head when the contentType is `text/html`", () => {
|
||||||
jest.spyOn(window.document.head, "insertBefore").mockImplementation((node) => {
|
jest.spyOn(window.document.head, "prepend").mockImplementation((node) => {
|
||||||
createdScriptElement = node as HTMLScriptElement;
|
createdScriptElement = node as HTMLScriptElement;
|
||||||
return node;
|
return node;
|
||||||
});
|
});
|
||||||
@ -28,16 +37,13 @@ describe("FIDO2 page-script for manifest v2", () => {
|
|||||||
|
|
||||||
expect(window.document.createElement).toHaveBeenCalledWith("script");
|
expect(window.document.createElement).toHaveBeenCalledWith("script");
|
||||||
expect(chrome.runtime.getURL).toHaveBeenCalledWith(Fido2ContentScript.PageScript);
|
expect(chrome.runtime.getURL).toHaveBeenCalledWith(Fido2ContentScript.PageScript);
|
||||||
expect(window.document.head.insertBefore).toHaveBeenCalledWith(
|
expect(window.document.head.prepend).toHaveBeenCalledWith(expect.any(HTMLScriptElement));
|
||||||
expect.any(HTMLScriptElement),
|
|
||||||
window.document.head.firstChild,
|
|
||||||
);
|
|
||||||
expect(createdScriptElement.src).toBe(`chrome-extension://id/${Fido2ContentScript.PageScript}`);
|
expect(createdScriptElement.src).toBe(`chrome-extension://id/${Fido2ContentScript.PageScript}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("appends the `page-script.js` file to the document element if the head is not available", () => {
|
it("appends the `page-script.js` file to the document element if the head is not available", () => {
|
||||||
window.document.documentElement.removeChild(window.document.head);
|
window.document.documentElement.removeChild(window.document.head);
|
||||||
jest.spyOn(window.document.documentElement, "insertBefore").mockImplementation((node) => {
|
jest.spyOn(window.document.documentElement, "prepend").mockImplementation((node) => {
|
||||||
createdScriptElement = node as HTMLScriptElement;
|
createdScriptElement = node as HTMLScriptElement;
|
||||||
return node;
|
return node;
|
||||||
});
|
});
|
||||||
@ -46,9 +52,8 @@ describe("FIDO2 page-script for manifest v2", () => {
|
|||||||
|
|
||||||
expect(window.document.createElement).toHaveBeenCalledWith("script");
|
expect(window.document.createElement).toHaveBeenCalledWith("script");
|
||||||
expect(chrome.runtime.getURL).toHaveBeenCalledWith(Fido2ContentScript.PageScript);
|
expect(chrome.runtime.getURL).toHaveBeenCalledWith(Fido2ContentScript.PageScript);
|
||||||
expect(window.document.documentElement.insertBefore).toHaveBeenCalledWith(
|
expect(window.document.documentElement.prepend).toHaveBeenCalledWith(
|
||||||
expect.any(HTMLScriptElement),
|
expect.any(HTMLScriptElement),
|
||||||
window.document.documentElement.firstChild,
|
|
||||||
);
|
);
|
||||||
expect(createdScriptElement.src).toBe(`chrome-extension://id/${Fido2ContentScript.PageScript}`);
|
expect(createdScriptElement.src).toBe(`chrome-extension://id/${Fido2ContentScript.PageScript}`);
|
||||||
});
|
});
|
||||||
@ -63,6 +68,7 @@ describe("FIDO2 page-script for manifest v2", () => {
|
|||||||
|
|
||||||
jest.spyOn(createdScriptElement, "remove");
|
jest.spyOn(createdScriptElement, "remove");
|
||||||
createdScriptElement.dispatchEvent(new Event("load"));
|
createdScriptElement.dispatchEvent(new Event("load"));
|
||||||
|
jest.runAllTimers();
|
||||||
|
|
||||||
expect(createdScriptElement.remove).toHaveBeenCalled();
|
expect(createdScriptElement.remove).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
@ -2,18 +2,20 @@
|
|||||||
* This script handles injection of the FIDO2 override page script into the document.
|
* This script handles injection of the FIDO2 override page script into the document.
|
||||||
* This is required for manifest v2, but will be removed when we migrate fully to manifest v3.
|
* This is required for manifest v2, but will be removed when we migrate fully to manifest v3.
|
||||||
*/
|
*/
|
||||||
import { Fido2ContentScript } from "../enums/fido2-content-script.enum";
|
|
||||||
|
|
||||||
(function (globalContext) {
|
(function (globalContext) {
|
||||||
if (globalContext.document.contentType !== "text/html") {
|
if (globalContext.document.contentType !== "text/html") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const script = globalContext.document.createElement("script");
|
const script = globalContext.document.createElement("script");
|
||||||
script.src = chrome.runtime.getURL(Fido2ContentScript.PageScript);
|
script.src = chrome.runtime.getURL("content/fido2-page-script.js");
|
||||||
script.addEventListener("load", () => script.remove());
|
script.addEventListener("load", removeScriptOnLoad);
|
||||||
|
|
||||||
const scriptInsertionPoint =
|
const scriptInsertionPoint =
|
||||||
globalContext.document.head || globalContext.document.documentElement;
|
globalContext.document.head || globalContext.document.documentElement;
|
||||||
scriptInsertionPoint.insertBefore(script, scriptInsertionPoint.firstChild);
|
scriptInsertionPoint.prepend(script);
|
||||||
|
|
||||||
|
function removeScriptOnLoad() {
|
||||||
|
globalThis.setTimeout(() => script?.remove(), 5000);
|
||||||
|
}
|
||||||
})(globalThis);
|
})(globalThis);
|
||||||
|
@ -2,26 +2,35 @@
|
|||||||
* This script handles injection of the FIDO2 override page script into the document.
|
* This script handles injection of the FIDO2 override page script into the document.
|
||||||
* This is required for manifest v2, but will be removed when we migrate fully to manifest v3.
|
* This is required for manifest v2, but will be removed when we migrate fully to manifest v3.
|
||||||
*/
|
*/
|
||||||
import { Fido2ContentScript } from "../enums/fido2-content-script.enum";
|
|
||||||
|
|
||||||
(function (globalContext) {
|
(function (globalContext) {
|
||||||
if (globalContext.document.contentType !== "text/html") {
|
if (globalContext.document.contentType !== "text/html") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (globalContext.document.readyState === "complete") {
|
const script = globalContext.document.createElement("script");
|
||||||
loadScript();
|
script.src = chrome.runtime.getURL("content/fido2-page-script.js");
|
||||||
|
script.addEventListener("load", removeScriptOnLoad);
|
||||||
|
|
||||||
|
// We are ensuring that the script injection is delayed in the event that we are loading
|
||||||
|
// within an iframe element. This prevents an issue with web mail clients that load content
|
||||||
|
// using ajax within iframes. In particular, Zimbra web mail client was observed to have this issue.
|
||||||
|
// @see https://github.com/bitwarden/clients/issues/9618
|
||||||
|
const delayScriptInjection =
|
||||||
|
globalContext.window.top !== globalContext.window &&
|
||||||
|
globalContext.document.readyState !== "complete";
|
||||||
|
if (delayScriptInjection) {
|
||||||
|
globalContext.document.addEventListener("DOMContentLoaded", injectScript);
|
||||||
} else {
|
} else {
|
||||||
globalContext.addEventListener("DOMContentLoaded", loadScript);
|
injectScript();
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadScript() {
|
function injectScript() {
|
||||||
const script = globalContext.document.createElement("script");
|
|
||||||
script.src = chrome.runtime.getURL(Fido2ContentScript.PageScript);
|
|
||||||
script.addEventListener("load", () => script.remove());
|
|
||||||
|
|
||||||
const scriptInsertionPoint =
|
const scriptInsertionPoint =
|
||||||
globalContext.document.head || globalContext.document.documentElement;
|
globalContext.document.head || globalContext.document.documentElement;
|
||||||
scriptInsertionPoint.insertBefore(script, scriptInsertionPoint.firstChild);
|
scriptInsertionPoint.prepend(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeScriptOnLoad() {
|
||||||
|
globalThis.setTimeout(() => script?.remove(), 5000);
|
||||||
}
|
}
|
||||||
})(globalThis);
|
})(globalThis);
|
||||||
|
Loading…
Reference in New Issue
Block a user