mirror of
https://github.com/bitwarden/browser.git
synced 2025-01-02 18:17:46 +01:00
[PM-5048] Query params are not persisting in extension popout window (#7019)
* [PM-5048] Query params are not persisting in extension popout window * [PM-5048] Reverting how we identify whether the user is popping out the current tab; * [PM-5048] Adding jest test to validate skipping parsing of the extension path * [PM-5048] Adding jest test to validate skipping parsing of the extension path * [PM-5048] Reworking implementation to ensure that popout window query params remain persistent * [PM-5048] Reworking implementation to ensure that appended query params do not remain persistent, but popout window query params do remain persistent. Fixing issues within vault item popouts and adding jest tests to verify those fixes * [PM-5048] Modifying how query params are set within vault popout windows * [PM-5048] Running prettier
This commit is contained in:
parent
483a197e4d
commit
7db844baf2
@ -191,25 +191,18 @@ describe("BrowserPopupUtils", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("replaces any existing `uilocation=` query params within the passed extension url path to state the the uilocaiton is a popup", async () => {
|
it("skips parsing the passed extension url path if the option to do that is set", () => {
|
||||||
const url = "popup/index.html#/tabs/vault?uilocation=sidebar";
|
const url = "popup/index.html?uilocation=popout#/tabs/vault";
|
||||||
jest.spyOn(BrowserPopupUtils as any, "isSingleActionPopoutOpen").mockResolvedValueOnce(false);
|
jest.spyOn(BrowserPopupUtils as any, "isSingleActionPopoutOpen").mockResolvedValueOnce(false);
|
||||||
|
jest.spyOn(BrowserPopupUtils as any, "buildPopoutUrl");
|
||||||
|
|
||||||
await BrowserPopupUtils.openPopout(url);
|
BrowserPopupUtils.openPopout(url);
|
||||||
|
|
||||||
expect(BrowserApi.createWindow).toHaveBeenCalledWith({
|
expect(BrowserPopupUtils["buildPopoutUrl"]).not.toHaveBeenCalled();
|
||||||
type: "popup",
|
|
||||||
focused: true,
|
|
||||||
width: 380,
|
|
||||||
height: 630,
|
|
||||||
left: 85,
|
|
||||||
top: 190,
|
|
||||||
url: `chrome-extension://id/popup/index.html#/tabs/vault?uilocation=popout`,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("appends the uilocation to the search params if an existing param is passed with the extension url path", async () => {
|
it("replaces any existing `uilocation=` query params within the passed extension url path to state the the uilocaiton is a popup", async () => {
|
||||||
const url = "popup/index.html#/tabs/vault?existingParam=123";
|
const url = "popup/index.html?uilocation=sidebar#/tabs/vault";
|
||||||
jest.spyOn(BrowserPopupUtils as any, "isSingleActionPopoutOpen").mockResolvedValueOnce(false);
|
jest.spyOn(BrowserPopupUtils as any, "isSingleActionPopoutOpen").mockResolvedValueOnce(false);
|
||||||
|
|
||||||
await BrowserPopupUtils.openPopout(url);
|
await BrowserPopupUtils.openPopout(url);
|
||||||
@ -221,7 +214,7 @@ describe("BrowserPopupUtils", () => {
|
|||||||
height: 630,
|
height: 630,
|
||||||
left: 85,
|
left: 85,
|
||||||
top: 190,
|
top: 190,
|
||||||
url: `chrome-extension://id/${url}&uilocation=popout`,
|
url: `chrome-extension://id/popup/index.html?uilocation=popout#/tabs/vault`,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -127,9 +127,7 @@ class BrowserPopupUtils {
|
|||||||
top: senderWindow.top + offsetTop,
|
top: senderWindow.top + offsetTop,
|
||||||
...defaultPopoutWindowOptions,
|
...defaultPopoutWindowOptions,
|
||||||
...windowOptions,
|
...windowOptions,
|
||||||
url: chrome.runtime.getURL(
|
url: BrowserPopupUtils.buildPopoutUrl(extensionUrlPath, singleActionKey),
|
||||||
BrowserPopupUtils.buildPopoutUrlPath(extensionUrlPath, singleActionKey),
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -252,23 +250,15 @@ class BrowserPopupUtils {
|
|||||||
* @param extensionUrlPath - A relative path to the extension page. Example: "popup/index.html#/tabs/vault"
|
* @param extensionUrlPath - A relative path to the extension page. Example: "popup/index.html#/tabs/vault"
|
||||||
* @param singleActionKey - The single action popout key used to identify the popout.
|
* @param singleActionKey - The single action popout key used to identify the popout.
|
||||||
*/
|
*/
|
||||||
private static buildPopoutUrlPath(extensionUrlPath: string, singleActionKey: string) {
|
private static buildPopoutUrl(extensionUrlPath: string, singleActionKey: string) {
|
||||||
let formattedExtensionUrlPath = extensionUrlPath;
|
const parsedUrl = new URL(chrome.runtime.getURL(extensionUrlPath));
|
||||||
if (formattedExtensionUrlPath.includes("uilocation=")) {
|
parsedUrl.searchParams.set("uilocation", "popout");
|
||||||
formattedExtensionUrlPath = formattedExtensionUrlPath.replace(
|
|
||||||
/uilocation=[^&]*/g,
|
|
||||||
"uilocation=popout",
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
formattedExtensionUrlPath +=
|
|
||||||
(formattedExtensionUrlPath.includes("?") ? "&" : "?") + "uilocation=popout";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (singleActionKey) {
|
if (singleActionKey) {
|
||||||
formattedExtensionUrlPath += `&singleActionPopout=${singleActionKey}`;
|
parsedUrl.searchParams.set("singleActionPopout", singleActionKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
return formattedExtensionUrlPath;
|
return parsedUrl.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,12 +5,14 @@ import { CipherType } from "@bitwarden/common/vault/enums";
|
|||||||
import BrowserPopupUtils from "../../../platform/popup/browser-popup-utils";
|
import BrowserPopupUtils from "../../../platform/popup/browser-popup-utils";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
openViewVaultItemPopout,
|
||||||
closeAddEditVaultItemPopout,
|
closeAddEditVaultItemPopout,
|
||||||
closeFido2Popout,
|
closeFido2Popout,
|
||||||
openAddEditVaultItemPopout,
|
openAddEditVaultItemPopout,
|
||||||
openFido2Popout,
|
openFido2Popout,
|
||||||
openVaultItemPasswordRepromptPopout,
|
openVaultItemPasswordRepromptPopout,
|
||||||
VaultPopoutType,
|
VaultPopoutType,
|
||||||
|
closeViewVaultItemPopout,
|
||||||
} from "./vault-popout-window";
|
} from "./vault-popout-window";
|
||||||
|
|
||||||
describe("VaultPopoutWindow", () => {
|
describe("VaultPopoutWindow", () => {
|
||||||
@ -25,6 +27,34 @@ describe("VaultPopoutWindow", () => {
|
|||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("openViewVaultItemPopout", () => {
|
||||||
|
it("opens a popout window that contains a sender tab id query param reference", async () => {
|
||||||
|
const senderTab = { id: 1, windowId: 2 } as chrome.tabs.Tab;
|
||||||
|
|
||||||
|
await openViewVaultItemPopout(senderTab, {
|
||||||
|
cipherId: "cipherId",
|
||||||
|
action: "action",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(openPopoutSpy).toHaveBeenCalledWith(
|
||||||
|
"popup/index.html#/view-cipher?cipherId=cipherId&senderTabId=1&action=action",
|
||||||
|
{
|
||||||
|
singleActionKey: `${VaultPopoutType.viewVaultItem}_cipherId`,
|
||||||
|
senderWindowId: 2,
|
||||||
|
forceCloseExistingWindows: undefined,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("closeViewVaultItemPopout", () => {
|
||||||
|
it("closes the view vault item popout window", async () => {
|
||||||
|
await closeViewVaultItemPopout("cipherId");
|
||||||
|
|
||||||
|
expect(closeSingleActionPopoutSpy).toHaveBeenCalledWith(`cipherId`, 0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("openVaultItemPasswordRepromptPopout", () => {
|
describe("openVaultItemPasswordRepromptPopout", () => {
|
||||||
it("opens a popout window that facilitates re-prompting for the password of a vault item", async () => {
|
it("opens a popout window that facilitates re-prompting for the password of a vault item", async () => {
|
||||||
const senderTab = { windowId: 1 } as chrome.tabs.Tab;
|
const senderTab = { windowId: 1 } as chrome.tabs.Tab;
|
||||||
@ -35,7 +65,7 @@ describe("VaultPopoutWindow", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(openPopoutSpy).toHaveBeenCalledWith(
|
expect(openPopoutSpy).toHaveBeenCalledWith(
|
||||||
"popup/index.html#/view-cipher?uilocation=popout&cipherId=cipherId&action=action",
|
"popup/index.html#/view-cipher?cipherId=cipherId&action=action",
|
||||||
{
|
{
|
||||||
singleActionKey: `${VaultPopoutType.viewVaultItem}_cipherId`,
|
singleActionKey: `${VaultPopoutType.viewVaultItem}_cipherId`,
|
||||||
senderWindowId: 1,
|
senderWindowId: 1,
|
||||||
@ -52,7 +82,7 @@ describe("VaultPopoutWindow", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(openPopoutSpy).toHaveBeenCalledWith(
|
expect(openPopoutSpy).toHaveBeenCalledWith(
|
||||||
"popup/index.html#/edit-cipher?uilocation=popout&uri=https://jest-testing-website.com",
|
"popup/index.html#/edit-cipher?uri=https://jest-testing-website.com",
|
||||||
{
|
{
|
||||||
singleActionKey: VaultPopoutType.addEditVaultItem,
|
singleActionKey: VaultPopoutType.addEditVaultItem,
|
||||||
senderWindowId: 1,
|
senderWindowId: 1,
|
||||||
@ -69,7 +99,7 @@ describe("VaultPopoutWindow", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(openPopoutSpy).toHaveBeenCalledWith(
|
expect(openPopoutSpy).toHaveBeenCalledWith(
|
||||||
`popup/index.html#/edit-cipher?uilocation=popout&type=${CipherType.Identity}&uri=https://jest-testing-website.com`,
|
`popup/index.html#/edit-cipher?type=${CipherType.Identity}&uri=https://jest-testing-website.com`,
|
||||||
{
|
{
|
||||||
singleActionKey: `${VaultPopoutType.addEditVaultItem}_${CipherType.Identity}`,
|
singleActionKey: `${VaultPopoutType.addEditVaultItem}_${CipherType.Identity}`,
|
||||||
senderWindowId: 1,
|
senderWindowId: 1,
|
||||||
@ -86,7 +116,7 @@ describe("VaultPopoutWindow", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(openPopoutSpy).toHaveBeenCalledWith(
|
expect(openPopoutSpy).toHaveBeenCalledWith(
|
||||||
"popup/index.html#/edit-cipher?uilocation=popout&cipherId=cipherId&uri=https://jest-testing-website.com",
|
"popup/index.html#/edit-cipher?cipherId=cipherId&uri=https://jest-testing-website.com",
|
||||||
{
|
{
|
||||||
singleActionKey: `${VaultPopoutType.addEditVaultItem}_cipherId`,
|
singleActionKey: `${VaultPopoutType.addEditVaultItem}_cipherId`,
|
||||||
senderWindowId: 1,
|
senderWindowId: 1,
|
||||||
|
@ -9,6 +9,12 @@ const VaultPopoutType = {
|
|||||||
fido2Popout: "vault_Fido2Popout",
|
fido2Popout: "vault_Fido2Popout",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a popout window that facilitates viewing a vault item.
|
||||||
|
*
|
||||||
|
* @param senderTab - The tab that sent the request.
|
||||||
|
* @param cipherOptions - The cipher id and action to perform.
|
||||||
|
*/
|
||||||
async function openViewVaultItemPopout(
|
async function openViewVaultItemPopout(
|
||||||
senderTab: chrome.tabs.Tab,
|
senderTab: chrome.tabs.Tab,
|
||||||
cipherOptions: {
|
cipherOptions: {
|
||||||
@ -18,15 +24,22 @@ async function openViewVaultItemPopout(
|
|||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
const { cipherId, action, forceCloseExistingWindows } = cipherOptions;
|
const { cipherId, action, forceCloseExistingWindows } = cipherOptions;
|
||||||
let promptWindowPath = "popup/index.html#/view-cipher?uilocation=popout";
|
let promptWindowPath = "popup/index.html#/view-cipher";
|
||||||
|
let queryParamToken = "?";
|
||||||
|
const formatQueryString = (key: string, value: string) => {
|
||||||
|
const queryString = `${queryParamToken}${key}=${value}`;
|
||||||
|
queryParamToken = "&";
|
||||||
|
return queryString;
|
||||||
|
};
|
||||||
|
|
||||||
if (cipherId) {
|
if (cipherId) {
|
||||||
promptWindowPath += `&cipherId=${cipherId}`;
|
promptWindowPath += formatQueryString("cipherId", cipherId);
|
||||||
}
|
}
|
||||||
if (senderTab.id) {
|
if (senderTab.id) {
|
||||||
promptWindowPath += `&senderTabId=${senderTab.id}`;
|
promptWindowPath += formatQueryString("senderTabId", String(senderTab.id));
|
||||||
}
|
}
|
||||||
if (action) {
|
if (action) {
|
||||||
promptWindowPath += `&action=${action}`;
|
promptWindowPath += formatQueryString("action", action);
|
||||||
}
|
}
|
||||||
|
|
||||||
await BrowserPopupUtils.openPopout(promptWindowPath, {
|
await BrowserPopupUtils.openPopout(promptWindowPath, {
|
||||||
@ -36,6 +49,12 @@ async function openViewVaultItemPopout(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the view vault item popout window.
|
||||||
|
*
|
||||||
|
* @param singleActionKey - The single action popout key used to identify the popout.
|
||||||
|
* @param delayClose - The amount of time to wait before closing the popout. Defaults to 0.
|
||||||
|
*/
|
||||||
async function closeViewVaultItemPopout(singleActionKey: string, delayClose = 0) {
|
async function closeViewVaultItemPopout(singleActionKey: string, delayClose = 0) {
|
||||||
await BrowserPopupUtils.closeSingleActionPopout(singleActionKey, delayClose);
|
await BrowserPopupUtils.closeSingleActionPopout(singleActionKey, delayClose);
|
||||||
}
|
}
|
||||||
@ -73,19 +92,25 @@ async function openAddEditVaultItemPopout(
|
|||||||
) {
|
) {
|
||||||
const { cipherId, cipherType } = cipherOptions;
|
const { cipherId, cipherType } = cipherOptions;
|
||||||
const { url, windowId } = senderTab;
|
const { url, windowId } = senderTab;
|
||||||
|
|
||||||
let singleActionKey = VaultPopoutType.addEditVaultItem;
|
let singleActionKey = VaultPopoutType.addEditVaultItem;
|
||||||
let addEditCipherUrl = "popup/index.html#/edit-cipher?uilocation=popout";
|
let addEditCipherUrl = "popup/index.html#/edit-cipher";
|
||||||
|
let queryParamToken = "?";
|
||||||
|
const formatQueryString = (key: string, value: string) => {
|
||||||
|
const queryString = `${queryParamToken}${key}=${value}`;
|
||||||
|
queryParamToken = "&";
|
||||||
|
return queryString;
|
||||||
|
};
|
||||||
|
|
||||||
if (cipherId && !cipherType) {
|
if (cipherId && !cipherType) {
|
||||||
singleActionKey += `_${cipherId}`;
|
singleActionKey += `_${cipherId}`;
|
||||||
addEditCipherUrl += `&cipherId=${cipherId}`;
|
addEditCipherUrl += formatQueryString("cipherId", cipherId);
|
||||||
}
|
}
|
||||||
if (cipherType && !cipherId) {
|
if (cipherType && !cipherId) {
|
||||||
singleActionKey += `_${cipherType}`;
|
singleActionKey += `_${cipherType}`;
|
||||||
addEditCipherUrl += `&type=${cipherType}`;
|
addEditCipherUrl += formatQueryString("type", String(cipherType));
|
||||||
}
|
}
|
||||||
if (senderTab.url) {
|
if (senderTab.url) {
|
||||||
addEditCipherUrl += `&uri=${url}`;
|
addEditCipherUrl += formatQueryString("uri", url);
|
||||||
}
|
}
|
||||||
|
|
||||||
await BrowserPopupUtils.openPopout(addEditCipherUrl, {
|
await BrowserPopupUtils.openPopout(addEditCipherUrl, {
|
||||||
|
Loading…
Reference in New Issue
Block a user