mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 08:13:42 +00:00
[PM-5189] Implementing jest tests for the OverlayBackground
This commit is contained in:
@@ -94,7 +94,7 @@ export type OverlayBackgroundExtensionMessageHandlers = {
|
|||||||
[key: string]: CallableFunction;
|
[key: string]: CallableFunction;
|
||||||
autofillOverlayElementClosed: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
autofillOverlayElementClosed: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
||||||
autofillOverlayAddNewVaultItem: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
autofillOverlayAddNewVaultItem: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
||||||
checkIsOverlayLoginCiphersPopulated: ({ sender }: BackgroundSenderParam) => void;
|
checkIsInlineMenuCiphersPopulated: ({ sender }: BackgroundSenderParam) => void;
|
||||||
updateFocusedFieldData: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
updateFocusedFieldData: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
||||||
updateIsFieldCurrentlyFocused: ({ message }: BackgroundMessageParam) => void;
|
updateIsFieldCurrentlyFocused: ({ message }: BackgroundMessageParam) => void;
|
||||||
checkIsFieldCurrentlyFocused: () => boolean;
|
checkIsFieldCurrentlyFocused: () => boolean;
|
||||||
|
|||||||
@@ -32,9 +32,14 @@ import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
|||||||
|
|
||||||
import { BrowserApi } from "../../platform/browser/browser-api";
|
import { BrowserApi } from "../../platform/browser/browser-api";
|
||||||
import { BrowserPlatformUtilsService } from "../../platform/services/platform-utils/browser-platform-utils.service";
|
import { BrowserPlatformUtilsService } from "../../platform/services/platform-utils/browser-platform-utils.service";
|
||||||
import { AutofillOverlayElement } from "../enums/autofill-overlay.enum";
|
import { AutofillOverlayElement, AutofillOverlayPort } from "../enums/autofill-overlay.enum";
|
||||||
import { AutofillService } from "../services/abstractions/autofill.service";
|
import { AutofillService } from "../services/abstractions/autofill.service";
|
||||||
import { createChromeTabMock, createAutofillPageDetailsMock } from "../spec/autofill-mocks";
|
import {
|
||||||
|
createChromeTabMock,
|
||||||
|
createAutofillPageDetailsMock,
|
||||||
|
createPortSpyMock,
|
||||||
|
createFocusedFieldDataMock,
|
||||||
|
} from "../spec/autofill-mocks";
|
||||||
import { flushPromises, sendMockExtensionMessage } from "../spec/testing-utils";
|
import { flushPromises, sendMockExtensionMessage } from "../spec/testing-utils";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -47,6 +52,7 @@ import { OverlayBackground } from "./overlay.background";
|
|||||||
|
|
||||||
describe("OverlayBackground", () => {
|
describe("OverlayBackground", () => {
|
||||||
const mockUserId = Utils.newGuid() as UserId;
|
const mockUserId = Utils.newGuid() as UserId;
|
||||||
|
const sendResponse = jest.fn();
|
||||||
let accountService: FakeAccountService;
|
let accountService: FakeAccountService;
|
||||||
let fakeStateProvider: FakeStateProvider;
|
let fakeStateProvider: FakeStateProvider;
|
||||||
let showFaviconsMock$: BehaviorSubject<boolean>;
|
let showFaviconsMock$: BehaviorSubject<boolean>;
|
||||||
@@ -70,8 +76,26 @@ describe("OverlayBackground", () => {
|
|||||||
let subFrameOffsetsSpy: SubFrameOffsetsForTab;
|
let subFrameOffsetsSpy: SubFrameOffsetsForTab;
|
||||||
let getFrameDetailsSpy: jest.SpyInstance;
|
let getFrameDetailsSpy: jest.SpyInstance;
|
||||||
let tabsSendMessageSpy: jest.SpyInstance;
|
let tabsSendMessageSpy: jest.SpyInstance;
|
||||||
|
let sendMessageSpy: jest.SpyInstance;
|
||||||
let getTabFromCurrentWindowIdSpy: jest.SpyInstance;
|
let getTabFromCurrentWindowIdSpy: jest.SpyInstance;
|
||||||
|
let buttonPortSpy: chrome.runtime.Port;
|
||||||
|
let listPortSpy: chrome.runtime.Port;
|
||||||
|
|
||||||
let getFrameCounter: number = 2;
|
let getFrameCounter: number = 2;
|
||||||
|
async function initOverlayElementPorts(options = { initList: true, initButton: true }) {
|
||||||
|
const { initList, initButton } = options;
|
||||||
|
if (initButton) {
|
||||||
|
await overlayBackground["handlePortOnConnect"](createPortSpyMock(AutofillOverlayPort.Button));
|
||||||
|
buttonPortSpy = overlayBackground["inlineMenuButtonPort"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initList) {
|
||||||
|
await overlayBackground["handlePortOnConnect"](createPortSpyMock(AutofillOverlayPort.List));
|
||||||
|
listPortSpy = overlayBackground["inlineMenuListPort"];
|
||||||
|
}
|
||||||
|
|
||||||
|
return { buttonPortSpy, listPortSpy };
|
||||||
|
}
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
accountService = mockAccountServiceWith(mockUserId);
|
accountService = mockAccountServiceWith(mockUserId);
|
||||||
@@ -125,6 +149,7 @@ describe("OverlayBackground", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
tabsSendMessageSpy = jest.spyOn(BrowserApi, "tabSendMessage");
|
tabsSendMessageSpy = jest.spyOn(BrowserApi, "tabSendMessage");
|
||||||
|
sendMessageSpy = jest.spyOn(BrowserApi, "sendMessage");
|
||||||
getTabFromCurrentWindowIdSpy = jest.spyOn(BrowserApi, "getTabFromCurrentWindowId");
|
getTabFromCurrentWindowIdSpy = jest.spyOn(BrowserApi, "getTabFromCurrentWindowId");
|
||||||
|
|
||||||
void overlayBackground.init();
|
void overlayBackground.init();
|
||||||
@@ -349,11 +374,17 @@ describe("OverlayBackground", () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
sender = mock<chrome.runtime.MessageSender>({ tab, frameId: middleFrameId });
|
sender = mock<chrome.runtime.MessageSender>({ tab, frameId: middleFrameId });
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
overlayBackground["isFieldCurrentlyFocused"] = true;
|
sendMockExtensionMessage({
|
||||||
|
command: "updateIsFieldCurrentlyFocused",
|
||||||
|
isFieldCurrentlyFocused: true,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("skips updating the position of either inline menu element if a field is not currently focused", async () => {
|
it("skips updating the position of either inline menu element if a field is not currently focused", async () => {
|
||||||
overlayBackground["isFieldCurrentlyFocused"] = false;
|
sendMockExtensionMessage({
|
||||||
|
command: "updateIsFieldCurrentlyFocused",
|
||||||
|
isFieldCurrentlyFocused: false,
|
||||||
|
});
|
||||||
|
|
||||||
sendMockExtensionMessage({ command: "rebuildSubFrameOffsets" }, sender);
|
sendMockExtensionMessage({ command: "rebuildSubFrameOffsets" }, sender);
|
||||||
await flushInlineMenuUpdatePromises();
|
await flushInlineMenuUpdatePromises();
|
||||||
@@ -430,7 +461,7 @@ describe("OverlayBackground", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("updateOverlayCiphers", () => {
|
describe("updating the overlay ciphers", () => {
|
||||||
const url = "https://jest-testing-website.com";
|
const url = "https://jest-testing-website.com";
|
||||||
const tab = createChromeTabMock({ url });
|
const tab = createChromeTabMock({ url });
|
||||||
const cipher1 = mock<CipherView>({
|
const cipher1 = mock<CipherView>({
|
||||||
@@ -480,7 +511,7 @@ describe("OverlayBackground", () => {
|
|||||||
expect(BrowserApi.getTabFromCurrentWindowId).toHaveBeenCalled();
|
expect(BrowserApi.getTabFromCurrentWindowId).toHaveBeenCalled();
|
||||||
expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledWith(url);
|
expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledWith(url);
|
||||||
expect(cipherService.sortCiphersByLastUsedThenName).toHaveBeenCalled();
|
expect(cipherService.sortCiphersByLastUsedThenName).toHaveBeenCalled();
|
||||||
expect(overlayBackground["overlayLoginCiphers"]).toStrictEqual(
|
expect(overlayBackground["inlineMenuCiphers"]).toStrictEqual(
|
||||||
new Map([
|
new Map([
|
||||||
["overlay-cipher-0", cipher2],
|
["overlay-cipher-0", cipher2],
|
||||||
["overlay-cipher-1", cipher1],
|
["overlay-cipher-1", cipher1],
|
||||||
@@ -535,4 +566,230 @@ describe("OverlayBackground", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("extension message handlers", () => {
|
||||||
|
describe("autofillOverlayElementClosed message handler", () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await initOverlayElementPorts();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("disconnects any expired ports if the sender is not from the same page as the most recently focused field", () => {
|
||||||
|
const port1 = mock<chrome.runtime.Port>();
|
||||||
|
const port2 = mock<chrome.runtime.Port>();
|
||||||
|
overlayBackground["expiredPorts"] = [port1, port2];
|
||||||
|
const sender = mock<chrome.runtime.MessageSender>({ tab: { id: 1 } });
|
||||||
|
const focusedFieldData = createFocusedFieldDataMock({ tabId: 2 });
|
||||||
|
sendMockExtensionMessage({ command: "updateFocusedFieldData", focusedFieldData });
|
||||||
|
|
||||||
|
sendMockExtensionMessage(
|
||||||
|
{
|
||||||
|
command: "autofillOverlayElementClosed",
|
||||||
|
overlayElement: AutofillOverlayElement.Button,
|
||||||
|
},
|
||||||
|
sender,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(port1.disconnect).toHaveBeenCalled();
|
||||||
|
expect(port2.disconnect).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("disconnects the button element port", () => {
|
||||||
|
sendMockExtensionMessage({
|
||||||
|
command: "autofillOverlayElementClosed",
|
||||||
|
overlayElement: AutofillOverlayElement.Button,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(buttonPortSpy.disconnect).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("disconnects the list element port", () => {
|
||||||
|
sendMockExtensionMessage({
|
||||||
|
command: "autofillOverlayElementClosed",
|
||||||
|
overlayElement: AutofillOverlayElement.List,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(listPortSpy.disconnect).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("autofillOverlayAddNewVaultItem message handler", () => {
|
||||||
|
let sender: chrome.runtime.MessageSender;
|
||||||
|
let openAddEditVaultItemPopoutSpy: jest.SpyInstance;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
sender = mock<chrome.runtime.MessageSender>({ tab: { id: 1 } });
|
||||||
|
openAddEditVaultItemPopoutSpy = jest
|
||||||
|
.spyOn(overlayBackground as any, "openAddEditVaultItemPopout")
|
||||||
|
.mockImplementation();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("will not open the add edit popout window if the message does not have a login cipher provided", () => {
|
||||||
|
sendMockExtensionMessage({ command: "autofillOverlayAddNewVaultItem" }, sender);
|
||||||
|
|
||||||
|
expect(cipherService.setAddEditCipherInfo).not.toHaveBeenCalled();
|
||||||
|
expect(openAddEditVaultItemPopoutSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("will open the add edit popout window after creating a new cipher", async () => {
|
||||||
|
sendMockExtensionMessage(
|
||||||
|
{
|
||||||
|
command: "autofillOverlayAddNewVaultItem",
|
||||||
|
login: {
|
||||||
|
uri: "https://tacos.com",
|
||||||
|
hostname: "",
|
||||||
|
username: "username",
|
||||||
|
password: "password",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sender,
|
||||||
|
);
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
expect(cipherService.setAddEditCipherInfo).toHaveBeenCalled();
|
||||||
|
expect(sendMessageSpy).toHaveBeenCalledWith("inlineAutofillMenuRefreshAddEditCipher");
|
||||||
|
expect(openAddEditVaultItemPopoutSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("checkIsInlineMenuCiphersPopulated message handler", () => {
|
||||||
|
let focusedFieldData: FocusedFieldData;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
focusedFieldData = createFocusedFieldDataMock();
|
||||||
|
sendMockExtensionMessage(
|
||||||
|
{ command: "updateFocusedFieldData", focusedFieldData },
|
||||||
|
mock<chrome.runtime.MessageSender>({ tab: { id: 2 }, frameId: 0 }),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns false if the sender's tab id is not equal to the focused field's tab id", async () => {
|
||||||
|
const sender = mock<chrome.runtime.MessageSender>({ tab: { id: 1 } });
|
||||||
|
|
||||||
|
sendMockExtensionMessage(
|
||||||
|
{ command: "checkIsInlineMenuCiphersPopulated" },
|
||||||
|
sender,
|
||||||
|
sendResponse,
|
||||||
|
);
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
expect(sendResponse).toHaveBeenCalledWith(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns false if the overlay login cipher are not populated", () => {});
|
||||||
|
|
||||||
|
it("returns true if the overlay login ciphers are populated", async () => {
|
||||||
|
overlayBackground["inlineMenuCiphers"] = new Map([
|
||||||
|
["overlay-cipher-0", mock<CipherView>()],
|
||||||
|
]);
|
||||||
|
|
||||||
|
sendMockExtensionMessage(
|
||||||
|
{ command: "checkIsInlineMenuCiphersPopulated" },
|
||||||
|
mock<chrome.runtime.MessageSender>({ tab: { id: 2 } }),
|
||||||
|
sendResponse,
|
||||||
|
);
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
expect(sendResponse).toHaveBeenCalledWith(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("checkIsFieldCurrentlyFocused message handler", () => {
|
||||||
|
it("returns true when a form field is currently focused", async () => {
|
||||||
|
sendMockExtensionMessage({
|
||||||
|
command: "updateIsFieldCurrentlyFocused",
|
||||||
|
isFieldCurrentlyFocused: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
sendMockExtensionMessage(
|
||||||
|
{ command: "checkIsFieldCurrentlyFocused" },
|
||||||
|
mock<chrome.runtime.MessageSender>(),
|
||||||
|
sendResponse,
|
||||||
|
);
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
expect(sendResponse).toHaveBeenCalledWith(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("checkIsFieldCurrentlyFilling message handler", () => {
|
||||||
|
it("returns true if autofill is currently running", async () => {
|
||||||
|
sendMockExtensionMessage({
|
||||||
|
command: "updateIsFieldCurrentlyFilling",
|
||||||
|
isFieldCurrentlyFilling: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
sendMockExtensionMessage(
|
||||||
|
{ command: "checkIsFieldCurrentlyFilling" },
|
||||||
|
mock<chrome.runtime.MessageSender>(),
|
||||||
|
sendResponse,
|
||||||
|
);
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
expect(sendResponse).toHaveBeenCalledWith(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getAutofillInlineMenuVisibility message handler", () => {
|
||||||
|
it("returns the current inline menu visibility setting", async () => {
|
||||||
|
sendMockExtensionMessage(
|
||||||
|
{ command: "getAutofillInlineMenuVisibility" },
|
||||||
|
mock<chrome.runtime.MessageSender>(),
|
||||||
|
sendResponse,
|
||||||
|
);
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
expect(sendResponse).toHaveBeenCalledWith(AutofillOverlayVisibility.OnFieldFocus);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("openAutofillInlineMenu", () => {
|
||||||
|
let sender: chrome.runtime.MessageSender;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
sender = mock<chrome.runtime.MessageSender>({ tab: { id: 1 } });
|
||||||
|
getTabFromCurrentWindowIdSpy.mockResolvedValue(sender.tab);
|
||||||
|
tabsSendMessageSpy.mockImplementation();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("opens the autofill inline menu by sending a message to the current tab", async () => {
|
||||||
|
sendMockExtensionMessage({ command: "openAutofillInlineMenu" }, sender);
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
expect(tabsSendMessageSpy).toHaveBeenCalledWith(
|
||||||
|
sender.tab,
|
||||||
|
{
|
||||||
|
command: "openAutofillInlineMenu",
|
||||||
|
isFocusingFieldElement: false,
|
||||||
|
isOpeningFullAutofillInlineMenu: false,
|
||||||
|
authStatus: 2,
|
||||||
|
},
|
||||||
|
{ frameId: 0 },
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sends the open menu message to the focused field's frameId", async () => {
|
||||||
|
sender.frameId = 10;
|
||||||
|
sendMockExtensionMessage({ command: "updateFocusedFieldData" }, sender);
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
sendMockExtensionMessage({ command: "openAutofillInlineMenu" }, sender);
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
expect(tabsSendMessageSpy).toHaveBeenCalledWith(
|
||||||
|
sender.tab,
|
||||||
|
{
|
||||||
|
command: "openAutofillInlineMenu",
|
||||||
|
isFocusingFieldElement: false,
|
||||||
|
isOpeningFullAutofillInlineMenu: false,
|
||||||
|
authStatus: 2,
|
||||||
|
},
|
||||||
|
{ frameId: 10 },
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("inline menu button message handlers", () => {});
|
||||||
|
|
||||||
|
describe("inline menu list message handlers", () => {});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
private readonly openUnlockPopout = openUnlockPopout;
|
private readonly openUnlockPopout = openUnlockPopout;
|
||||||
private readonly openViewVaultItemPopout = openViewVaultItemPopout;
|
private readonly openViewVaultItemPopout = openViewVaultItemPopout;
|
||||||
private readonly openAddEditVaultItemPopout = openAddEditVaultItemPopout;
|
private readonly openAddEditVaultItemPopout = openAddEditVaultItemPopout;
|
||||||
private overlayLoginCiphers: Map<string, CipherView> = new Map();
|
private inlineMenuCiphers: Map<string, CipherView> = new Map();
|
||||||
private pageDetailsForTab: PageDetailsForTab = {};
|
private pageDetailsForTab: PageDetailsForTab = {};
|
||||||
private subFrameOffsetsForTab: SubFrameOffsetsForTab = {};
|
private subFrameOffsetsForTab: SubFrameOffsetsForTab = {};
|
||||||
private updateInlineMenuPositionTimeout: number | NodeJS.Timeout;
|
private updateInlineMenuPositionTimeout: number | NodeJS.Timeout;
|
||||||
@@ -67,8 +67,8 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
autofillOverlayElementClosed: ({ message, sender }) =>
|
autofillOverlayElementClosed: ({ message, sender }) =>
|
||||||
this.overlayElementClosed(message, sender),
|
this.overlayElementClosed(message, sender),
|
||||||
autofillOverlayAddNewVaultItem: ({ message, sender }) => this.addNewVaultItem(message, sender),
|
autofillOverlayAddNewVaultItem: ({ message, sender }) => this.addNewVaultItem(message, sender),
|
||||||
checkIsOverlayLoginCiphersPopulated: ({ sender }) =>
|
checkIsInlineMenuCiphersPopulated: ({ sender }) =>
|
||||||
this.checkIsOverlayLoginCiphersPopulated(sender),
|
this.checkIsInlineMenuCiphersPopulated(sender),
|
||||||
updateFocusedFieldData: ({ message, sender }) => this.setFocusedFieldData(message, sender),
|
updateFocusedFieldData: ({ message, sender }) => this.setFocusedFieldData(message, sender),
|
||||||
updateIsFieldCurrentlyFocused: ({ message }) => this.updateIsFieldCurrentlyFocused(message),
|
updateIsFieldCurrentlyFocused: ({ message }) => this.updateIsFieldCurrentlyFocused(message),
|
||||||
checkIsFieldCurrentlyFocused: () => this.checkIsFieldCurrentlyFocused(),
|
checkIsFieldCurrentlyFocused: () => this.checkIsFieldCurrentlyFocused(),
|
||||||
@@ -179,12 +179,12 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.overlayLoginCiphers = new Map();
|
this.inlineMenuCiphers = new Map();
|
||||||
const ciphersViews = (await this.cipherService.getAllDecryptedForUrl(currentTab.url)).sort(
|
const ciphersViews = (await this.cipherService.getAllDecryptedForUrl(currentTab.url)).sort(
|
||||||
(a, b) => this.cipherService.sortCiphersByLastUsedThenName(a, b),
|
(a, b) => this.cipherService.sortCiphersByLastUsedThenName(a, b),
|
||||||
);
|
);
|
||||||
for (let cipherIndex = 0; cipherIndex < ciphersViews.length; cipherIndex++) {
|
for (let cipherIndex = 0; cipherIndex < ciphersViews.length; cipherIndex++) {
|
||||||
this.overlayLoginCiphers.set(`overlay-cipher-${cipherIndex}`, ciphersViews[cipherIndex]);
|
this.inlineMenuCiphers.set(`overlay-cipher-${cipherIndex}`, ciphersViews[cipherIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ciphers = await this.getOverlayCipherData();
|
const ciphers = await this.getOverlayCipherData();
|
||||||
@@ -200,7 +200,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
*/
|
*/
|
||||||
private async getOverlayCipherData(): Promise<OverlayCipherData[]> {
|
private async getOverlayCipherData(): Promise<OverlayCipherData[]> {
|
||||||
const showFavicons = await firstValueFrom(this.domainSettingsService.showFavicons$);
|
const showFavicons = await firstValueFrom(this.domainSettingsService.showFavicons$);
|
||||||
const overlayCiphersArray = Array.from(this.overlayLoginCiphers);
|
const overlayCiphersArray = Array.from(this.inlineMenuCiphers);
|
||||||
const overlayCipherData: OverlayCipherData[] = [];
|
const overlayCipherData: OverlayCipherData[] = [];
|
||||||
|
|
||||||
for (let cipherIndex = 0; cipherIndex < overlayCiphersArray.length; cipherIndex++) {
|
for (let cipherIndex = 0; cipherIndex < overlayCiphersArray.length; cipherIndex++) {
|
||||||
@@ -388,7 +388,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
);
|
);
|
||||||
if (
|
if (
|
||||||
mostRecentlyFocusedFieldHasValue &&
|
mostRecentlyFocusedFieldHasValue &&
|
||||||
(this.checkIsOverlayLoginCiphersPopulated(sender) ||
|
(this.checkIsInlineMenuCiphersPopulated(sender) ||
|
||||||
(await this.getAuthStatus()) !== AuthenticationStatus.Unlocked)
|
(await this.getAuthStatus()) !== AuthenticationStatus.Unlocked)
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
@@ -401,7 +401,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
* Triggers autofill for the selected cipher in the inline menu list. Also places
|
* Triggers autofill for the selected cipher in the inline menu list. Also places
|
||||||
* the selected cipher at the top of the list of ciphers.
|
* the selected cipher at the top of the list of ciphers.
|
||||||
*
|
*
|
||||||
* @param overlayCipherId - Cipher ID corresponding to the overlayLoginCiphers map. Does not correspond to the actual cipher's ID.
|
* @param overlayCipherId - Cipher ID corresponding to the inlineMenuCiphers map. Does not correspond to the actual cipher's ID.
|
||||||
* @param sender - The sender of the port message
|
* @param sender - The sender of the port message
|
||||||
*/
|
*/
|
||||||
private async fillSelectedInlineMenuListItem(
|
private async fillSelectedInlineMenuListItem(
|
||||||
@@ -413,7 +413,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cipher = this.overlayLoginCiphers.get(overlayCipherId);
|
const cipher = this.inlineMenuCiphers.get(overlayCipherId);
|
||||||
|
|
||||||
if (await this.autofillService.isPasswordRepromptRequired(cipher, sender.tab)) {
|
if (await this.autofillService.isPasswordRepromptRequired(cipher, sender.tab)) {
|
||||||
return;
|
return;
|
||||||
@@ -430,7 +430,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
this.platformUtilsService.copyToClipboard(totpCode);
|
this.platformUtilsService.copyToClipboard(totpCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.overlayLoginCiphers = new Map([[overlayCipherId, cipher], ...this.overlayLoginCiphers]);
|
this.inlineMenuCiphers = new Map([[overlayCipherId, cipher], ...this.inlineMenuCiphers]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -801,14 +801,14 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
/**
|
/**
|
||||||
* Triggers the opening of a vault item popout window associated
|
* Triggers the opening of a vault item popout window associated
|
||||||
* with the passed cipher ID.
|
* with the passed cipher ID.
|
||||||
* @param overlayCipherId - Cipher ID corresponding to the overlayLoginCiphers map. Does not correspond to the actual cipher's ID.
|
* @param overlayCipherId - Cipher ID corresponding to the inlineMenuCiphers map. Does not correspond to the actual cipher's ID.
|
||||||
* @param sender - The sender of the port message
|
* @param sender - The sender of the port message
|
||||||
*/
|
*/
|
||||||
private async viewSelectedCipher(
|
private async viewSelectedCipher(
|
||||||
{ overlayCipherId }: OverlayPortMessage,
|
{ overlayCipherId }: OverlayPortMessage,
|
||||||
{ sender }: chrome.runtime.Port,
|
{ sender }: chrome.runtime.Port,
|
||||||
) {
|
) {
|
||||||
const cipher = this.overlayLoginCiphers.get(overlayCipherId);
|
const cipher = this.inlineMenuCiphers.get(overlayCipherId);
|
||||||
if (!cipher) {
|
if (!cipher) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -945,18 +945,34 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
await BrowserApi.sendMessage("inlineAutofillMenuRefreshAddEditCipher");
|
await BrowserApi.sendMessage("inlineAutofillMenuRefreshAddEditCipher");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the property that identifies if a form field set up for the inline menu is currently focused.
|
||||||
|
*
|
||||||
|
* @param message - The message received from the web page
|
||||||
|
*/
|
||||||
private updateIsFieldCurrentlyFocused(message: OverlayBackgroundExtensionMessage) {
|
private updateIsFieldCurrentlyFocused(message: OverlayBackgroundExtensionMessage) {
|
||||||
this.isFieldCurrentlyFocused = message.isFieldCurrentlyFocused;
|
this.isFieldCurrentlyFocused = message.isFieldCurrentlyFocused;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows a content script to check if a form field setup for the inline menu is currently focused.
|
||||||
|
*/
|
||||||
private checkIsFieldCurrentlyFocused() {
|
private checkIsFieldCurrentlyFocused() {
|
||||||
return this.isFieldCurrentlyFocused;
|
return this.isFieldCurrentlyFocused;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the property that identifies if a form field is currently being autofilled.
|
||||||
|
*
|
||||||
|
* @param message - The message received from the web page
|
||||||
|
*/
|
||||||
private updateIsFieldCurrentlyFilling(message: OverlayBackgroundExtensionMessage) {
|
private updateIsFieldCurrentlyFilling(message: OverlayBackgroundExtensionMessage) {
|
||||||
this.isFieldCurrentlyFilling = message.isFieldCurrentlyFilling;
|
this.isFieldCurrentlyFilling = message.isFieldCurrentlyFilling;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows a content script to check if a form field is currently being autofilled.
|
||||||
|
*/
|
||||||
private checkIsFieldCurrentlyFilling() {
|
private checkIsFieldCurrentlyFilling() {
|
||||||
return this.isFieldCurrentlyFilling;
|
return this.isFieldCurrentlyFilling;
|
||||||
}
|
}
|
||||||
@@ -977,8 +993,8 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private checkIsOverlayLoginCiphersPopulated(sender: chrome.runtime.MessageSender) {
|
private checkIsInlineMenuCiphersPopulated(sender: chrome.runtime.MessageSender) {
|
||||||
return sender.tab.id === this.focusedFieldData.tabId && this.overlayLoginCiphers.size > 0;
|
return sender.tab.id === this.focusedFieldData.tabId && this.inlineMenuCiphers.size > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateInlineMenuButtonColorScheme() {
|
private updateInlineMenuButtonColorScheme() {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export class AutofillInlineMenuIframeService implements AutofillInlineMenuIframe
|
|||||||
private ariaAlertTimeout: number | NodeJS.Timeout;
|
private ariaAlertTimeout: number | NodeJS.Timeout;
|
||||||
private delayedCloseTimeout: number | NodeJS.Timeout;
|
private delayedCloseTimeout: number | NodeJS.Timeout;
|
||||||
private readonly fadeInOpacityTransition = "opacity 125ms ease-out 0s";
|
private readonly fadeInOpacityTransition = "opacity 125ms ease-out 0s";
|
||||||
private readonly fadeOutOpacityTransition = "opacity 75ms ease-in 0s";
|
private readonly fadeOutOpacityTransition = "opacity 60ms ease-out 0s";
|
||||||
private iframeStyles: Partial<CSSStyleDeclaration> = {
|
private iframeStyles: Partial<CSSStyleDeclaration> = {
|
||||||
all: "initial",
|
all: "initial",
|
||||||
position: "fixed",
|
position: "fixed",
|
||||||
|
|||||||
@@ -1022,7 +1022,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async isInlineMenuCiphersPopulated() {
|
private async isInlineMenuCiphersPopulated() {
|
||||||
return (await this.sendExtensionMessage("checkIsOverlayLoginCiphersPopulated")) === true;
|
return (await this.sendExtensionMessage("checkIsInlineMenuCiphersPopulated")) === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user