mirror of
https://github.com/bitwarden/browser
synced 2025-12-18 17:23:37 +00:00
[PM-6921] Optimize methodology for storing page details within inline menu background processes (#8385)
* [PM-6921] Optimize methodology for storing page details within inline menu background processes * [PM-6921] Incorporating method for ensuring that we clear the Map datastructure when the page details are being removed * [PM-6921] Adjusting method to ensure that page details always remain up to date for when processed
This commit is contained in:
@@ -125,7 +125,8 @@ describe("OverlayBackground", () => {
|
|||||||
describe("removePageDetails", () => {
|
describe("removePageDetails", () => {
|
||||||
it("removes the page details for a specific tab from the pageDetailsForTab object", () => {
|
it("removes the page details for a specific tab from the pageDetailsForTab object", () => {
|
||||||
const tabId = 1;
|
const tabId = 1;
|
||||||
overlayBackground["pageDetailsForTab"][tabId] = [createPageDetailMock()];
|
const frameId = 2;
|
||||||
|
overlayBackground["pageDetailsForTab"][tabId] = new Map([[frameId, createPageDetailMock()]]);
|
||||||
overlayBackground.removePageDetails(tabId);
|
overlayBackground.removePageDetails(tabId);
|
||||||
|
|
||||||
expect(overlayBackground["pageDetailsForTab"][tabId]).toBeUndefined();
|
expect(overlayBackground["pageDetailsForTab"][tabId]).toBeUndefined();
|
||||||
@@ -864,29 +865,40 @@ describe("OverlayBackground", () => {
|
|||||||
sender,
|
sender,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(overlayBackground["pageDetailsForTab"][sender.tab.id]).toStrictEqual([
|
expect(overlayBackground["pageDetailsForTab"][sender.tab.id]).toStrictEqual(
|
||||||
{ frameId: sender.frameId, tab: sender.tab, details: pageDetails1 },
|
new Map([
|
||||||
]);
|
[sender.frameId, { frameId: sender.frameId, tab: sender.tab, details: pageDetails1 }],
|
||||||
|
]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("updates the page details for a tab that already has a set of page details stored ", () => {
|
it("updates the page details for a tab that already has a set of page details stored ", () => {
|
||||||
overlayBackground["pageDetailsForTab"][sender.tab.id] = [
|
const secondFrameSender = mock<chrome.runtime.MessageSender>({
|
||||||
{
|
tab: { id: 1 },
|
||||||
frameId: sender.frameId,
|
frameId: 3,
|
||||||
tab: sender.tab,
|
});
|
||||||
details: pageDetails1,
|
overlayBackground["pageDetailsForTab"][sender.tab.id] = new Map([
|
||||||
},
|
[sender.frameId, { frameId: sender.frameId, tab: sender.tab, details: pageDetails1 }],
|
||||||
];
|
]);
|
||||||
|
|
||||||
sendExtensionRuntimeMessage(
|
sendExtensionRuntimeMessage(
|
||||||
{ command: "collectPageDetailsResponse", details: pageDetails2 },
|
{ command: "collectPageDetailsResponse", details: pageDetails2 },
|
||||||
sender,
|
secondFrameSender,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(overlayBackground["pageDetailsForTab"][sender.tab.id]).toStrictEqual([
|
expect(overlayBackground["pageDetailsForTab"][sender.tab.id]).toStrictEqual(
|
||||||
{ frameId: sender.frameId, tab: sender.tab, details: pageDetails1 },
|
new Map([
|
||||||
{ frameId: sender.frameId, tab: sender.tab, details: pageDetails2 },
|
[sender.frameId, { frameId: sender.frameId, tab: sender.tab, details: pageDetails1 }],
|
||||||
]);
|
[
|
||||||
|
secondFrameSender.frameId,
|
||||||
|
{
|
||||||
|
frameId: secondFrameSender.frameId,
|
||||||
|
tab: secondFrameSender.tab,
|
||||||
|
details: pageDetails2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1196,6 +1208,10 @@ describe("OverlayBackground", () => {
|
|||||||
let getLoginCiphersSpy: jest.SpyInstance;
|
let getLoginCiphersSpy: jest.SpyInstance;
|
||||||
let isPasswordRepromptRequiredSpy: jest.SpyInstance;
|
let isPasswordRepromptRequiredSpy: jest.SpyInstance;
|
||||||
let doAutoFillSpy: jest.SpyInstance;
|
let doAutoFillSpy: jest.SpyInstance;
|
||||||
|
let sender: chrome.runtime.MessageSender;
|
||||||
|
const pageDetails = createAutofillPageDetailsMock({
|
||||||
|
login: { username: "username1", password: "password1" },
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
getLoginCiphersSpy = jest.spyOn(overlayBackground["overlayLoginCiphers"], "get");
|
getLoginCiphersSpy = jest.spyOn(overlayBackground["overlayLoginCiphers"], "get");
|
||||||
@@ -1204,6 +1220,7 @@ describe("OverlayBackground", () => {
|
|||||||
"isPasswordRepromptRequired",
|
"isPasswordRepromptRequired",
|
||||||
);
|
);
|
||||||
doAutoFillSpy = jest.spyOn(overlayBackground["autofillService"], "doAutoFill");
|
doAutoFillSpy = jest.spyOn(overlayBackground["autofillService"], "doAutoFill");
|
||||||
|
sender = mock<chrome.runtime.MessageSender>({ tab: { id: 1 } });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("ignores the fill request if the overlay cipher id is not provided", async () => {
|
it("ignores the fill request if the overlay cipher id is not provided", async () => {
|
||||||
@@ -1215,12 +1232,27 @@ describe("OverlayBackground", () => {
|
|||||||
expect(doAutoFillSpy).not.toHaveBeenCalled();
|
expect(doAutoFillSpy).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("ignores the fill request if the tab does not contain any identified page details", async () => {
|
||||||
|
sendPortMessage(listPortSpy, {
|
||||||
|
command: "fillSelectedListItem",
|
||||||
|
overlayCipherId: "overlay-cipher-1",
|
||||||
|
});
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
expect(getLoginCiphersSpy).not.toHaveBeenCalled();
|
||||||
|
expect(isPasswordRepromptRequiredSpy).not.toHaveBeenCalled();
|
||||||
|
expect(doAutoFillSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
it("ignores the fill request if a master password reprompt is required", async () => {
|
it("ignores the fill request if a master password reprompt is required", async () => {
|
||||||
const cipher = mock<CipherView>({
|
const cipher = mock<CipherView>({
|
||||||
reprompt: CipherRepromptType.Password,
|
reprompt: CipherRepromptType.Password,
|
||||||
type: CipherType.Login,
|
type: CipherType.Login,
|
||||||
});
|
});
|
||||||
overlayBackground["overlayLoginCiphers"] = new Map([["overlay-cipher-1", cipher]]);
|
overlayBackground["overlayLoginCiphers"] = new Map([["overlay-cipher-1", cipher]]);
|
||||||
|
overlayBackground["pageDetailsForTab"][sender.tab.id] = new Map([
|
||||||
|
[sender.frameId, { frameId: sender.frameId, tab: sender.tab, details: pageDetails }],
|
||||||
|
]);
|
||||||
getLoginCiphersSpy = jest.spyOn(overlayBackground["overlayLoginCiphers"], "get");
|
getLoginCiphersSpy = jest.spyOn(overlayBackground["overlayLoginCiphers"], "get");
|
||||||
isPasswordRepromptRequiredSpy.mockResolvedValue(true);
|
isPasswordRepromptRequiredSpy.mockResolvedValue(true);
|
||||||
|
|
||||||
@@ -1247,6 +1279,14 @@ describe("OverlayBackground", () => {
|
|||||||
["overlay-cipher-2", cipher2],
|
["overlay-cipher-2", cipher2],
|
||||||
["overlay-cipher-3", cipher3],
|
["overlay-cipher-3", cipher3],
|
||||||
]);
|
]);
|
||||||
|
const pageDetailsForTab = {
|
||||||
|
frameId: sender.frameId,
|
||||||
|
tab: sender.tab,
|
||||||
|
details: pageDetails,
|
||||||
|
};
|
||||||
|
overlayBackground["pageDetailsForTab"][sender.tab.id] = new Map([
|
||||||
|
[sender.frameId, pageDetailsForTab],
|
||||||
|
]);
|
||||||
isPasswordRepromptRequiredSpy.mockResolvedValue(false);
|
isPasswordRepromptRequiredSpy.mockResolvedValue(false);
|
||||||
|
|
||||||
sendPortMessage(listPortSpy, {
|
sendPortMessage(listPortSpy, {
|
||||||
@@ -1262,7 +1302,7 @@ describe("OverlayBackground", () => {
|
|||||||
expect(doAutoFillSpy).toHaveBeenCalledWith({
|
expect(doAutoFillSpy).toHaveBeenCalledWith({
|
||||||
tab: listPortSpy.sender.tab,
|
tab: listPortSpy.sender.tab,
|
||||||
cipher: cipher2,
|
cipher: cipher2,
|
||||||
pageDetails: undefined,
|
pageDetails: [pageDetailsForTab],
|
||||||
fillNewPassword: true,
|
fillNewPassword: true,
|
||||||
allowTotpAutofill: true,
|
allowTotpAutofill: true,
|
||||||
});
|
});
|
||||||
@@ -1278,6 +1318,9 @@ describe("OverlayBackground", () => {
|
|||||||
it("copies the cipher's totp code to the clipboard after filling", async () => {
|
it("copies the cipher's totp code to the clipboard after filling", async () => {
|
||||||
const cipher1 = mock<CipherView>({ id: "overlay-cipher-1" });
|
const cipher1 = mock<CipherView>({ id: "overlay-cipher-1" });
|
||||||
overlayBackground["overlayLoginCiphers"] = new Map([["overlay-cipher-1", cipher1]]);
|
overlayBackground["overlayLoginCiphers"] = new Map([["overlay-cipher-1", cipher1]]);
|
||||||
|
overlayBackground["pageDetailsForTab"][sender.tab.id] = new Map([
|
||||||
|
[sender.frameId, { frameId: sender.frameId, tab: sender.tab, details: pageDetails }],
|
||||||
|
]);
|
||||||
isPasswordRepromptRequiredSpy.mockResolvedValue(false);
|
isPasswordRepromptRequiredSpy.mockResolvedValue(false);
|
||||||
const copyToClipboardSpy = jest
|
const copyToClipboardSpy = jest
|
||||||
.spyOn(overlayBackground["platformUtilsService"], "copyToClipboard")
|
.spyOn(overlayBackground["platformUtilsService"], "copyToClipboard")
|
||||||
|
|||||||
@@ -47,7 +47,10 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
private readonly openViewVaultItemPopout = openViewVaultItemPopout;
|
private readonly openViewVaultItemPopout = openViewVaultItemPopout;
|
||||||
private readonly openAddEditVaultItemPopout = openAddEditVaultItemPopout;
|
private readonly openAddEditVaultItemPopout = openAddEditVaultItemPopout;
|
||||||
private overlayLoginCiphers: Map<string, CipherView> = new Map();
|
private overlayLoginCiphers: Map<string, CipherView> = new Map();
|
||||||
private pageDetailsForTab: Record<number, PageDetail[]> = {};
|
private pageDetailsForTab: Record<
|
||||||
|
chrome.runtime.MessageSender["tab"]["id"],
|
||||||
|
Map<chrome.runtime.MessageSender["frameId"], PageDetail>
|
||||||
|
> = {};
|
||||||
private userAuthStatus: AuthenticationStatus = AuthenticationStatus.LoggedOut;
|
private userAuthStatus: AuthenticationStatus = AuthenticationStatus.LoggedOut;
|
||||||
private overlayButtonPort: chrome.runtime.Port;
|
private overlayButtonPort: chrome.runtime.Port;
|
||||||
private overlayListPort: chrome.runtime.Port;
|
private overlayListPort: chrome.runtime.Port;
|
||||||
@@ -107,6 +110,11 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
* @param tabId - Used to reference the page details of a specific tab
|
* @param tabId - Used to reference the page details of a specific tab
|
||||||
*/
|
*/
|
||||||
removePageDetails(tabId: number) {
|
removePageDetails(tabId: number) {
|
||||||
|
if (!this.pageDetailsForTab[tabId]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.pageDetailsForTab[tabId].clear();
|
||||||
delete this.pageDetailsForTab[tabId];
|
delete this.pageDetailsForTab[tabId];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,12 +211,13 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
details: message.details,
|
details: message.details,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.pageDetailsForTab[sender.tab.id]?.length) {
|
const pageDetailsMap = this.pageDetailsForTab[sender.tab.id];
|
||||||
this.pageDetailsForTab[sender.tab.id].push(pageDetails);
|
if (!pageDetailsMap) {
|
||||||
|
this.pageDetailsForTab[sender.tab.id] = new Map([[sender.frameId, pageDetails]]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.pageDetailsForTab[sender.tab.id] = [pageDetails];
|
pageDetailsMap.set(sender.frameId, pageDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -222,7 +231,8 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
{ overlayCipherId }: OverlayPortMessage,
|
{ overlayCipherId }: OverlayPortMessage,
|
||||||
{ sender }: chrome.runtime.Port,
|
{ sender }: chrome.runtime.Port,
|
||||||
) {
|
) {
|
||||||
if (!overlayCipherId) {
|
const pageDetails = this.pageDetailsForTab[sender.tab.id];
|
||||||
|
if (!overlayCipherId || !pageDetails?.size) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,7 +244,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
const totpCode = await this.autofillService.doAutoFill({
|
const totpCode = await this.autofillService.doAutoFill({
|
||||||
tab: sender.tab,
|
tab: sender.tab,
|
||||||
cipher: cipher,
|
cipher: cipher,
|
||||||
pageDetails: this.pageDetailsForTab[sender.tab.id],
|
pageDetails: Array.from(pageDetails.values()),
|
||||||
fillNewPassword: true,
|
fillNewPassword: true,
|
||||||
allowTotpAutofill: true,
|
allowTotpAutofill: true,
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user