mirror of
https://github.com/bitwarden/browser
synced 2025-12-19 09:43:23 +00:00
[PM-5189] Refactoring implementation
This commit is contained in:
@@ -144,7 +144,7 @@ type InlineMenuListPortMessageHandlers = {
|
|||||||
forceCloseAutofillInlineMenu: ({ port }: PortConnectionParam) => void;
|
forceCloseAutofillInlineMenu: ({ port }: PortConnectionParam) => void;
|
||||||
autofillInlineMenuBlurred: () => void;
|
autofillInlineMenuBlurred: () => void;
|
||||||
unlockVault: ({ port }: PortConnectionParam) => void;
|
unlockVault: ({ port }: PortConnectionParam) => void;
|
||||||
fillSelectedListItem: ({ message, port }: PortOnMessageHandlerParams) => void;
|
fillSelectedAutofillInlineMenuListItem: ({ message, port }: PortOnMessageHandlerParams) => void;
|
||||||
addNewVaultItem: ({ port }: PortConnectionParam) => void;
|
addNewVaultItem: ({ port }: PortConnectionParam) => void;
|
||||||
viewSelectedCipher: ({ message, port }: PortOnMessageHandlerParams) => void;
|
viewSelectedCipher: ({ message, port }: PortOnMessageHandlerParams) => void;
|
||||||
redirectAutofillInlineMenuFocusOut: ({ message, port }: PortOnMessageHandlerParams) => void;
|
redirectAutofillInlineMenuFocusOut: ({ message, port }: PortOnMessageHandlerParams) => void;
|
||||||
|
|||||||
@@ -402,12 +402,12 @@ describe("OverlayBackground", () => {
|
|||||||
const authStatus = AuthenticationStatus.Unlocked;
|
const authStatus = AuthenticationStatus.Unlocked;
|
||||||
overlayBackground["userAuthStatus"] = AuthenticationStatus.Unlocked;
|
overlayBackground["userAuthStatus"] = AuthenticationStatus.Unlocked;
|
||||||
authService.activeAccountStatus$ = new BehaviorSubject(authStatus);
|
authService.activeAccountStatus$ = new BehaviorSubject(authStatus);
|
||||||
jest.spyOn(overlayBackground as any, "updateOverlayButtonAuthStatus").mockImplementation();
|
jest.spyOn(overlayBackground as any, "updateInlineMenuButtonAuthStatus").mockImplementation();
|
||||||
jest.spyOn(overlayBackground as any, "updateOverlayCiphers").mockImplementation();
|
jest.spyOn(overlayBackground as any, "updateOverlayCiphers").mockImplementation();
|
||||||
|
|
||||||
const status = await overlayBackground["getAuthStatus"]();
|
const status = await overlayBackground["getAuthStatus"]();
|
||||||
|
|
||||||
expect(overlayBackground["updateOverlayButtonAuthStatus"]).not.toHaveBeenCalled();
|
expect(overlayBackground["updateInlineMenuButtonAuthStatus"]).not.toHaveBeenCalled();
|
||||||
expect(overlayBackground["updateOverlayCiphers"]).not.toHaveBeenCalled();
|
expect(overlayBackground["updateOverlayCiphers"]).not.toHaveBeenCalled();
|
||||||
expect(overlayBackground["userAuthStatus"]).toBe(authStatus);
|
expect(overlayBackground["userAuthStatus"]).toBe(authStatus);
|
||||||
expect(status).toBe(authStatus);
|
expect(status).toBe(authStatus);
|
||||||
@@ -417,41 +417,41 @@ describe("OverlayBackground", () => {
|
|||||||
const authStatus = AuthenticationStatus.Unlocked;
|
const authStatus = AuthenticationStatus.Unlocked;
|
||||||
overlayBackground["userAuthStatus"] = AuthenticationStatus.LoggedOut;
|
overlayBackground["userAuthStatus"] = AuthenticationStatus.LoggedOut;
|
||||||
authService.activeAccountStatus$ = new BehaviorSubject(authStatus);
|
authService.activeAccountStatus$ = new BehaviorSubject(authStatus);
|
||||||
jest.spyOn(overlayBackground as any, "updateOverlayButtonAuthStatus").mockImplementation();
|
jest.spyOn(overlayBackground as any, "updateInlineMenuButtonAuthStatus").mockImplementation();
|
||||||
jest.spyOn(overlayBackground as any, "updateOverlayCiphers").mockImplementation();
|
jest.spyOn(overlayBackground as any, "updateOverlayCiphers").mockImplementation();
|
||||||
|
|
||||||
await overlayBackground["getAuthStatus"]();
|
await overlayBackground["getAuthStatus"]();
|
||||||
|
|
||||||
expect(overlayBackground["updateOverlayButtonAuthStatus"]).toHaveBeenCalled();
|
expect(overlayBackground["updateInlineMenuButtonAuthStatus"]).toHaveBeenCalled();
|
||||||
expect(overlayBackground["updateOverlayCiphers"]).toHaveBeenCalled();
|
expect(overlayBackground["updateOverlayCiphers"]).toHaveBeenCalled();
|
||||||
expect(overlayBackground["userAuthStatus"]).toBe(authStatus);
|
expect(overlayBackground["userAuthStatus"]).toBe(authStatus);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("updateOverlayButtonAuthStatus", () => {
|
describe("updateInlineMenuButtonAuthStatus", () => {
|
||||||
it("will send a message to the button port with the user's auth status", () => {
|
it("will send a message to the button port with the user's auth status", () => {
|
||||||
overlayBackground["inlineMenuButtonPort"] = mock<chrome.runtime.Port>();
|
overlayBackground["inlineMenuButtonPort"] = mock<chrome.runtime.Port>();
|
||||||
jest.spyOn(overlayBackground["inlineMenuButtonPort"], "postMessage");
|
jest.spyOn(overlayBackground["inlineMenuButtonPort"], "postMessage");
|
||||||
|
|
||||||
overlayBackground["updateOverlayButtonAuthStatus"]();
|
overlayBackground["updateInlineMenuButtonAuthStatus"]();
|
||||||
|
|
||||||
expect(overlayBackground["inlineMenuButtonPort"].postMessage).toHaveBeenCalledWith({
|
expect(overlayBackground["inlineMenuButtonPort"].postMessage).toHaveBeenCalledWith({
|
||||||
command: "updateOverlayButtonAuthStatus",
|
command: "updateInlineMenuButtonAuthStatus",
|
||||||
authStatus: overlayBackground["userAuthStatus"],
|
authStatus: overlayBackground["userAuthStatus"],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("getTranslations", () => {
|
describe("getInlineMenuTranslations", () => {
|
||||||
it("will query the overlay page translations if they have not been queried", () => {
|
it("will query the overlay page translations if they have not been queried", () => {
|
||||||
overlayBackground["inlineMenuPageTranslations"] = undefined;
|
overlayBackground["inlineMenuPageTranslations"] = undefined;
|
||||||
jest.spyOn(overlayBackground as any, "getTranslations");
|
jest.spyOn(overlayBackground as any, "getInlineMenuTranslations");
|
||||||
jest.spyOn(overlayBackground["i18nService"], "translate").mockImplementation((key) => key);
|
jest.spyOn(overlayBackground["i18nService"], "translate").mockImplementation((key) => key);
|
||||||
jest.spyOn(BrowserApi, "getUILanguage").mockReturnValue("en");
|
jest.spyOn(BrowserApi, "getUILanguage").mockReturnValue("en");
|
||||||
|
|
||||||
const translations = overlayBackground["getTranslations"]();
|
const translations = overlayBackground["getInlineMenuTranslations"]();
|
||||||
|
|
||||||
expect(overlayBackground["getTranslations"]).toHaveBeenCalled();
|
expect(overlayBackground["getInlineMenuTranslations"]).toHaveBeenCalled();
|
||||||
const translationKeys = [
|
const translationKeys = [
|
||||||
"opensInANewWindow",
|
"opensInANewWindow",
|
||||||
"bitwardenOverlayButton",
|
"bitwardenOverlayButton",
|
||||||
@@ -540,7 +540,9 @@ describe("OverlayBackground", () => {
|
|||||||
};
|
};
|
||||||
const sender = mock<chrome.runtime.MessageSender>({ tab: { id: 1 } });
|
const sender = mock<chrome.runtime.MessageSender>({ tab: { id: 1 } });
|
||||||
const sendResponse = jest.fn();
|
const sendResponse = jest.fn();
|
||||||
jest.spyOn(overlayBackground as any, "getTranslations").mockReturnValue("translations");
|
jest
|
||||||
|
.spyOn(overlayBackground as any, "getInlineMenuTranslations")
|
||||||
|
.mockReturnValue("translations");
|
||||||
|
|
||||||
const returnValue = overlayBackground["handleExtensionMessage"](
|
const returnValue = overlayBackground["handleExtensionMessage"](
|
||||||
message,
|
message,
|
||||||
@@ -677,7 +679,7 @@ describe("OverlayBackground", () => {
|
|||||||
sendMockExtensionMessage({ command: "checkAutofillInlineMenuFocused" });
|
sendMockExtensionMessage({ command: "checkAutofillInlineMenuFocused" });
|
||||||
|
|
||||||
expect(listPortSpy.postMessage).toHaveBeenCalledWith({
|
expect(listPortSpy.postMessage).toHaveBeenCalledWith({
|
||||||
command: "checkAutofillOverlayListFocused",
|
command: "checkAutofillInlineMenuListFocused",
|
||||||
});
|
});
|
||||||
expect(buttonPortSpy.postMessage).not.toHaveBeenCalledWith({
|
expect(buttonPortSpy.postMessage).not.toHaveBeenCalledWith({
|
||||||
command: "checkAutofillInlineMenuButtonFocused",
|
command: "checkAutofillInlineMenuButtonFocused",
|
||||||
@@ -693,7 +695,7 @@ describe("OverlayBackground", () => {
|
|||||||
command: "checkAutofillInlineMenuButtonFocused",
|
command: "checkAutofillInlineMenuButtonFocused",
|
||||||
});
|
});
|
||||||
expect(listPortSpy.postMessage).not.toHaveBeenCalledWith({
|
expect(listPortSpy.postMessage).not.toHaveBeenCalledWith({
|
||||||
command: "checkAutofillOverlayListFocused",
|
command: "checkAutofillInlineMenuListFocused",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1041,7 +1043,7 @@ describe("OverlayBackground", () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.spyOn(overlayBackground as any, "updateInlineMenuPosition").mockImplementation();
|
jest.spyOn(overlayBackground as any, "updateInlineMenuPosition").mockImplementation();
|
||||||
jest.spyOn(overlayBackground as any, "getAuthStatus").mockImplementation();
|
jest.spyOn(overlayBackground as any, "getAuthStatus").mockImplementation();
|
||||||
jest.spyOn(overlayBackground as any, "getTranslations").mockImplementation();
|
jest.spyOn(overlayBackground as any, "getInlineMenuTranslations").mockImplementation();
|
||||||
jest.spyOn(overlayBackground as any, "getOverlayCipherData").mockImplementation();
|
jest.spyOn(overlayBackground as any, "getOverlayCipherData").mockImplementation();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1067,7 +1069,7 @@ describe("OverlayBackground", () => {
|
|||||||
expect(listPortSpy.postMessage).toHaveBeenCalled();
|
expect(listPortSpy.postMessage).toHaveBeenCalled();
|
||||||
expect(overlayBackground["getAuthStatus"]).toHaveBeenCalled();
|
expect(overlayBackground["getAuthStatus"]).toHaveBeenCalled();
|
||||||
expect(chrome.runtime.getURL).toHaveBeenCalledWith("overlay/list.css");
|
expect(chrome.runtime.getURL).toHaveBeenCalledWith("overlay/list.css");
|
||||||
expect(overlayBackground["getTranslations"]).toHaveBeenCalled();
|
expect(overlayBackground["getInlineMenuTranslations"]).toHaveBeenCalled();
|
||||||
expect(overlayBackground["getOverlayCipherData"]).toHaveBeenCalled();
|
expect(overlayBackground["getOverlayCipherData"]).toHaveBeenCalled();
|
||||||
expect(overlayBackground["updateInlineMenuPosition"]).toHaveBeenCalledWith(
|
expect(overlayBackground["updateInlineMenuPosition"]).toHaveBeenCalledWith(
|
||||||
{ overlayElement: AutofillOverlayElement.List },
|
{ overlayElement: AutofillOverlayElement.List },
|
||||||
@@ -1088,7 +1090,7 @@ describe("OverlayBackground", () => {
|
|||||||
expect(buttonPortSpy.postMessage).toHaveBeenCalled();
|
expect(buttonPortSpy.postMessage).toHaveBeenCalled();
|
||||||
expect(overlayBackground["getAuthStatus"]).toHaveBeenCalled();
|
expect(overlayBackground["getAuthStatus"]).toHaveBeenCalled();
|
||||||
expect(chrome.runtime.getURL).toHaveBeenCalledWith("overlay/button.css");
|
expect(chrome.runtime.getURL).toHaveBeenCalledWith("overlay/button.css");
|
||||||
expect(overlayBackground["getTranslations"]).toHaveBeenCalled();
|
expect(overlayBackground["getInlineMenuTranslations"]).toHaveBeenCalled();
|
||||||
expect(overlayBackground["updateInlineMenuPosition"]).toHaveBeenCalledWith(
|
expect(overlayBackground["updateInlineMenuPosition"]).toHaveBeenCalledWith(
|
||||||
{ overlayElement: AutofillOverlayElement.Button },
|
{ overlayElement: AutofillOverlayElement.Button },
|
||||||
buttonPortSpy.sender,
|
buttonPortSpy.sender,
|
||||||
@@ -1318,7 +1320,7 @@ describe("OverlayBackground", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("fillSelectedListItem", () => {
|
describe("fillSelectedAutofillInlineMenuListItem", () => {
|
||||||
let getLoginCiphersSpy: jest.SpyInstance;
|
let getLoginCiphersSpy: jest.SpyInstance;
|
||||||
let isPasswordRepromptRequiredSpy: jest.SpyInstance;
|
let isPasswordRepromptRequiredSpy: jest.SpyInstance;
|
||||||
let doAutoFillSpy: jest.SpyInstance;
|
let doAutoFillSpy: jest.SpyInstance;
|
||||||
@@ -1339,7 +1341,7 @@ describe("OverlayBackground", () => {
|
|||||||
|
|
||||||
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 () => {
|
||||||
sendPortMessage(listMessageConnectorPortSpy, {
|
sendPortMessage(listMessageConnectorPortSpy, {
|
||||||
command: "fillSelectedListItem",
|
command: "fillSelectedAutofillInlineMenuListItem",
|
||||||
portKey,
|
portKey,
|
||||||
});
|
});
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
@@ -1351,7 +1353,7 @@ describe("OverlayBackground", () => {
|
|||||||
|
|
||||||
it("ignores the fill request if the tab does not contain any identified page details", async () => {
|
it("ignores the fill request if the tab does not contain any identified page details", async () => {
|
||||||
sendPortMessage(listMessageConnectorPortSpy, {
|
sendPortMessage(listMessageConnectorPortSpy, {
|
||||||
command: "fillSelectedListItem",
|
command: "fillSelectedAutofillInlineMenuListItem",
|
||||||
overlayCipherId: "overlay-cipher-1",
|
overlayCipherId: "overlay-cipher-1",
|
||||||
portKey,
|
portKey,
|
||||||
});
|
});
|
||||||
@@ -1375,7 +1377,7 @@ describe("OverlayBackground", () => {
|
|||||||
isPasswordRepromptRequiredSpy.mockResolvedValue(true);
|
isPasswordRepromptRequiredSpy.mockResolvedValue(true);
|
||||||
|
|
||||||
sendPortMessage(listMessageConnectorPortSpy, {
|
sendPortMessage(listMessageConnectorPortSpy, {
|
||||||
command: "fillSelectedListItem",
|
command: "fillSelectedAutofillInlineMenuListItem",
|
||||||
overlayCipherId: "overlay-cipher-1",
|
overlayCipherId: "overlay-cipher-1",
|
||||||
portKey,
|
portKey,
|
||||||
});
|
});
|
||||||
@@ -1409,7 +1411,7 @@ describe("OverlayBackground", () => {
|
|||||||
isPasswordRepromptRequiredSpy.mockResolvedValue(false);
|
isPasswordRepromptRequiredSpy.mockResolvedValue(false);
|
||||||
|
|
||||||
sendPortMessage(listMessageConnectorPortSpy, {
|
sendPortMessage(listMessageConnectorPortSpy, {
|
||||||
command: "fillSelectedListItem",
|
command: "fillSelectedAutofillInlineMenuListItem",
|
||||||
overlayCipherId: "overlay-cipher-2",
|
overlayCipherId: "overlay-cipher-2",
|
||||||
portKey,
|
portKey,
|
||||||
});
|
});
|
||||||
@@ -1448,7 +1450,7 @@ describe("OverlayBackground", () => {
|
|||||||
doAutoFillSpy.mockReturnValueOnce("totp-code");
|
doAutoFillSpy.mockReturnValueOnce("totp-code");
|
||||||
|
|
||||||
sendPortMessage(listMessageConnectorPortSpy, {
|
sendPortMessage(listMessageConnectorPortSpy, {
|
||||||
command: "fillSelectedListItem",
|
command: "fillSelectedAutofillInlineMenuListItem",
|
||||||
overlayCipherId: "overlay-cipher-2",
|
overlayCipherId: "overlay-cipher-2",
|
||||||
portKey,
|
portKey,
|
||||||
});
|
});
|
||||||
@@ -1533,7 +1535,7 @@ describe("OverlayBackground", () => {
|
|||||||
};
|
};
|
||||||
const redirectOverlayFocusOutSpy = jest.spyOn(
|
const redirectOverlayFocusOutSpy = jest.spyOn(
|
||||||
overlayBackground as any,
|
overlayBackground as any,
|
||||||
"redirectAutofillInlineMenuFocusOut",
|
"redirectInlineMenuFocusOut",
|
||||||
);
|
);
|
||||||
|
|
||||||
sendPortMessage(listMessageConnectorPortSpy, message);
|
sendPortMessage(listMessageConnectorPortSpy, message);
|
||||||
|
|||||||
@@ -109,7 +109,8 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
this.closeInlineMenu(port.sender, { forceCloseAutofillInlineMenu: true }),
|
this.closeInlineMenu(port.sender, { forceCloseAutofillInlineMenu: true }),
|
||||||
autofillInlineMenuBlurred: () => this.checkInlineMenuButtonFocused(),
|
autofillInlineMenuBlurred: () => this.checkInlineMenuButtonFocused(),
|
||||||
unlockVault: ({ port }) => this.unlockVault(port),
|
unlockVault: ({ port }) => this.unlockVault(port),
|
||||||
fillSelectedListItem: ({ message, port }) => this.fillSelectedOverlayListItem(message, port),
|
fillSelectedAutofillInlineMenuListItem: ({ message, port }) =>
|
||||||
|
this.fillSelectedInlineMenuListItem(message, port),
|
||||||
addNewVaultItem: ({ port }) => this.getNewVaultItemDetails(port),
|
addNewVaultItem: ({ port }) => this.getNewVaultItemDetails(port),
|
||||||
viewSelectedCipher: ({ message, port }) => this.viewSelectedCipher(message, port),
|
viewSelectedCipher: ({ message, port }) => this.viewSelectedCipher(message, port),
|
||||||
redirectAutofillInlineMenuFocusOut: ({ message, port }) =>
|
redirectAutofillInlineMenuFocusOut: ({ message, port }) =>
|
||||||
@@ -166,7 +167,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the overlay list's ciphers and sends the updated list to the overlay list iframe.
|
* Updates the inline menu list's ciphers and sends the updated list to the inline menu list iframe.
|
||||||
* Queries all ciphers for the given url, and sorts them by last used. Will not update the
|
* Queries all ciphers for the given url, and sorts them by last used. Will not update the
|
||||||
* list of ciphers if the extension is not unlocked.
|
* list of ciphers if the extension is not unlocked.
|
||||||
*/
|
*/
|
||||||
@@ -194,7 +195,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Strips out unnecessary data from the ciphers and returns an array of
|
* Strips out unnecessary data from the ciphers and returns an array of
|
||||||
* objects that contain the cipher data needed for the overlay list.
|
* objects that contain the cipher data needed for the inline menu list.
|
||||||
*/
|
*/
|
||||||
private async getOverlayCipherData(): Promise<OverlayCipherData[]> {
|
private async getOverlayCipherData(): Promise<OverlayCipherData[]> {
|
||||||
const showFavicons = await firstValueFrom(this.domainSettingsService.showFavicons$);
|
const showFavicons = await firstValueFrom(this.domainSettingsService.showFavicons$);
|
||||||
@@ -347,13 +348,13 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggers autofill for the selected cipher in the overlay 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 overlayLoginCiphers 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 fillSelectedOverlayListItem(
|
private async fillSelectedInlineMenuListItem(
|
||||||
{ overlayCipherId }: OverlayPortMessage,
|
{ overlayCipherId }: OverlayPortMessage,
|
||||||
{ sender }: chrome.runtime.Port,
|
{ sender }: chrome.runtime.Port,
|
||||||
) {
|
) {
|
||||||
@@ -383,8 +384,8 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the overlay is focused. Will check the overlay list
|
* Checks if the inline menu is focused. Will check the inline menu list
|
||||||
* if it is open, otherwise it will check the overlay button.
|
* if it is open, otherwise it will check the inline menu button.
|
||||||
*/
|
*/
|
||||||
private checkInlineMenuFocused() {
|
private checkInlineMenuFocused() {
|
||||||
if (this.inlineMenuListPort) {
|
if (this.inlineMenuListPort) {
|
||||||
@@ -397,24 +398,24 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Posts a message to the overlay button iframe to check if it is focused.
|
* Posts a message to the inline menu button iframe to check if it is focused.
|
||||||
*/
|
*/
|
||||||
private checkInlineMenuButtonFocused() {
|
private checkInlineMenuButtonFocused() {
|
||||||
this.inlineMenuButtonPort?.postMessage({ command: "checkAutofillInlineMenuButtonFocused" });
|
this.inlineMenuButtonPort?.postMessage({ command: "checkAutofillInlineMenuButtonFocused" });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Posts a message to the overlay list iframe to check if it is focused.
|
* Posts a message to the inline menu list iframe to check if it is focused.
|
||||||
*/
|
*/
|
||||||
private checkInlineMenuListFocused() {
|
private checkInlineMenuListFocused() {
|
||||||
this.inlineMenuListPort?.postMessage({ command: "checkAutofillOverlayListFocused" });
|
this.inlineMenuListPort?.postMessage({ command: "checkAutofillInlineMenuListFocused" });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a message to the sender tab to close the autofill overlay.
|
* Sends a message to the sender tab to close the autofill inline menu.
|
||||||
*
|
*
|
||||||
* @param sender - The sender of the port message
|
* @param sender - The sender of the port message
|
||||||
* @param forceCloseAutofillInlineMenu - Identifies whether the overlay should be forced closed
|
* @param forceCloseAutofillInlineMenu - Identifies whether the inline menu should be forced closed
|
||||||
* @param overlayElement - The overlay element to close, either the list or button
|
* @param overlayElement - The overlay element to close, either the list or button
|
||||||
*/
|
*/
|
||||||
private closeInlineMenu(
|
private closeInlineMenu(
|
||||||
@@ -475,7 +476,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the position of either the overlay list or button. The position
|
* Updates the position of either the inline menu list or button. The position
|
||||||
* is based on the focused field's position and dimensions.
|
* is based on the focused field's position and dimensions.
|
||||||
*
|
*
|
||||||
* @param overlayElement - The overlay element to update, either the list or button
|
* @param overlayElement - The overlay element to update, either the list or button
|
||||||
@@ -504,7 +505,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
if (overlayElement === AutofillOverlayElement.Button) {
|
if (overlayElement === AutofillOverlayElement.Button) {
|
||||||
this.inlineMenuButtonPort?.postMessage({
|
this.inlineMenuButtonPort?.postMessage({
|
||||||
command: "updateIframePosition",
|
command: "updateIframePosition",
|
||||||
styles: this.getOverlayButtonPosition(subFrameOffsets),
|
styles: this.getInlineMenuButtonPosition(subFrameOffsets),
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -512,15 +513,15 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
|
|
||||||
this.inlineMenuListPort?.postMessage({
|
this.inlineMenuListPort?.postMessage({
|
||||||
command: "updateIframePosition",
|
command: "updateIframePosition",
|
||||||
styles: this.getOverlayListPosition(subFrameOffsets),
|
styles: this.getInlineMenuListPosition(subFrameOffsets),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the position of the focused field and calculates the position
|
* Gets the position of the focused field and calculates the position
|
||||||
* of the overlay button based on the focused field's position and dimensions.
|
* of the inline menu button based on the focused field's position and dimensions.
|
||||||
*/
|
*/
|
||||||
private getOverlayButtonPosition(subFrameOffsets: SubFrameOffsetData) {
|
private getInlineMenuButtonPosition(subFrameOffsets: SubFrameOffsetData) {
|
||||||
if (!this.focusedFieldData) {
|
if (!this.focusedFieldData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -555,9 +556,9 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the position of the focused field and calculates the position
|
* Gets the position of the focused field and calculates the position
|
||||||
* of the overlay list based on the focused field's position and dimensions.
|
* of the inline menu list based on the focused field's position and dimensions.
|
||||||
*/
|
*/
|
||||||
private getOverlayListPosition(subFrameOffsets: SubFrameOffsetData) {
|
private getInlineMenuListPosition(subFrameOffsets: SubFrameOffsetData) {
|
||||||
if (!this.focusedFieldData) {
|
if (!this.focusedFieldData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -587,9 +588,9 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the overlay's visibility based on the display property passed in the extension message.
|
* Updates the inline menu's visibility based on the display property passed in the extension message.
|
||||||
*
|
*
|
||||||
* @param display - The display property of the overlay, either "block" or "none"
|
* @param display - The display property of the inline menu, either "block" or "none"
|
||||||
* @param sender - The sender of the extension message
|
* @param sender - The sender of the extension message
|
||||||
*/
|
*/
|
||||||
private updateInlineMenuHidden(
|
private updateInlineMenuHidden(
|
||||||
@@ -617,10 +618,10 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a message to the currently active tab to open the autofill overlay.
|
* Sends a message to the currently active tab to open the autofill inline menu.
|
||||||
*
|
*
|
||||||
* @param isFocusingFieldElement - Identifies whether the field element should be focused when the overlay is opened
|
* @param isFocusingFieldElement - Identifies whether the field element should be focused when the inline menu is opened
|
||||||
* @param isOpeningFullAutofillInlineMenu - Identifies whether the full overlay should be forced open regardless of other states
|
* @param isOpeningFullAutofillInlineMenu - Identifies whether the full inline menu should be forced open regardless of other states
|
||||||
*/
|
*/
|
||||||
private async openInlineMenu(
|
private async openInlineMenu(
|
||||||
isFocusingFieldElement = false,
|
isFocusingFieldElement = false,
|
||||||
@@ -643,16 +644,16 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the overlay's visibility setting from the settings service.
|
* Gets the inline menu's visibility setting from the settings service.
|
||||||
*/
|
*/
|
||||||
private async getInlineMenuVisibility(): Promise<InlineMenuVisibilitySetting> {
|
private async getInlineMenuVisibility(): Promise<InlineMenuVisibilitySetting> {
|
||||||
return await firstValueFrom(this.autofillSettingsService.inlineMenuVisibility$);
|
return await firstValueFrom(this.autofillSettingsService.inlineMenuVisibility$);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the user's authentication status from the auth service. If the user's
|
* Gets the user's authentication status from the auth service. If the user's authentication
|
||||||
* authentication status has changed, the overlay button's authentication status
|
* status has changed, the inline menu button's authentication status will be updated
|
||||||
* will be updated and the overlay list's ciphers will be updated.
|
* and the inline menu list's ciphers will be updated.
|
||||||
*/
|
*/
|
||||||
private async getAuthStatus() {
|
private async getAuthStatus() {
|
||||||
const formerAuthStatus = this.userAuthStatus;
|
const formerAuthStatus = this.userAuthStatus;
|
||||||
@@ -662,7 +663,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
this.userAuthStatus !== formerAuthStatus &&
|
this.userAuthStatus !== formerAuthStatus &&
|
||||||
this.userAuthStatus === AuthenticationStatus.Unlocked
|
this.userAuthStatus === AuthenticationStatus.Unlocked
|
||||||
) {
|
) {
|
||||||
this.updateOverlayButtonAuthStatus();
|
this.updateInlineMenuButtonAuthStatus();
|
||||||
await this.updateOverlayCiphers();
|
await this.updateOverlayCiphers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -670,21 +671,21 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a message to the overlay button to update its authentication status.
|
* Sends a message to the inline menu button to update its authentication status.
|
||||||
*/
|
*/
|
||||||
private updateOverlayButtonAuthStatus() {
|
private updateInlineMenuButtonAuthStatus() {
|
||||||
this.inlineMenuButtonPort?.postMessage({
|
this.inlineMenuButtonPort?.postMessage({
|
||||||
command: "updateOverlayButtonAuthStatus",
|
command: "updateInlineMenuButtonAuthStatus",
|
||||||
authStatus: this.userAuthStatus,
|
authStatus: this.userAuthStatus,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the overlay button being clicked. If the user is not authenticated,
|
* Handles the inline menu button being clicked. If the user is not authenticated,
|
||||||
* the vault will be unlocked. If the user is authenticated, the overlay will
|
* the vault will be unlocked. If the user is authenticated, the inline menu will
|
||||||
* be opened.
|
* be opened.
|
||||||
*
|
*
|
||||||
* @param port - The port of the overlay button
|
* @param port - The port of the inline menu button
|
||||||
*/
|
*/
|
||||||
private handleInlineMenuButtonClicked(port: chrome.runtime.Port) {
|
private handleInlineMenuButtonClicked(port: chrome.runtime.Port) {
|
||||||
if (this.userAuthStatus !== AuthenticationStatus.Unlocked) {
|
if (this.userAuthStatus !== AuthenticationStatus.Unlocked) {
|
||||||
@@ -698,7 +699,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
/**
|
/**
|
||||||
* Facilitates opening the unlock popout window.
|
* Facilitates opening the unlock popout window.
|
||||||
*
|
*
|
||||||
* @param port - The port of the overlay list
|
* @param port - The port of the inline menu list
|
||||||
*/
|
*/
|
||||||
private async unlockVault(port: chrome.runtime.Port) {
|
private async unlockVault(port: chrome.runtime.Port) {
|
||||||
const { sender } = port;
|
const { sender } = port;
|
||||||
@@ -738,14 +739,14 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Facilitates redirecting focus to the overlay list.
|
* Facilitates redirecting focus to the inline menu list.
|
||||||
*/
|
*/
|
||||||
private focusInlineMenuList() {
|
private focusInlineMenuList() {
|
||||||
this.inlineMenuListPort?.postMessage({ command: "focusInlineMenuList" });
|
this.inlineMenuListPort?.postMessage({ command: "focusInlineMenuList" });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the authentication status for the user and opens the overlay if
|
* Updates the authentication status for the user and opens the inline menu if
|
||||||
* a followup command is present in the message.
|
* a followup command is present in the message.
|
||||||
*
|
*
|
||||||
* @param message - Extension message received from the `unlockCompleted` command
|
* @param message - Extension message received from the `unlockCompleted` command
|
||||||
@@ -759,9 +760,9 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the translations for the overlay page.
|
* Gets the translations for the inline menu page.
|
||||||
*/
|
*/
|
||||||
private getTranslations() {
|
private getInlineMenuTranslations() {
|
||||||
if (!this.inlineMenuPageTranslations) {
|
if (!this.inlineMenuPageTranslations) {
|
||||||
this.inlineMenuPageTranslations = {
|
this.inlineMenuPageTranslations = {
|
||||||
locale: BrowserApi.getUILanguage(),
|
locale: BrowserApi.getUILanguage(),
|
||||||
@@ -785,7 +786,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Facilitates redirecting focus out of one of the
|
* Facilitates redirecting focus out of one of the
|
||||||
* overlay elements to elements on the page.
|
* inline menu elements to elements on the page.
|
||||||
*
|
*
|
||||||
* @param direction - The direction to redirect focus to (either "next", "previous" or "current)
|
* @param direction - The direction to redirect focus to (either "next", "previous" or "current)
|
||||||
* @param sender - The sender of the port message
|
* @param sender - The sender of the port message
|
||||||
@@ -952,21 +953,21 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
* @param port - The port that connected to the extension background
|
* @param port - The port that connected to the extension background
|
||||||
*/
|
*/
|
||||||
private handlePortOnConnect = async (port: chrome.runtime.Port) => {
|
private handlePortOnConnect = async (port: chrome.runtime.Port) => {
|
||||||
const isOverlayListMessageConnector = port.name === AutofillOverlayPort.ListMessageConnector;
|
const isInlineMenuListMessageConnector = port.name === AutofillOverlayPort.ListMessageConnector;
|
||||||
const isOverlayButtonMessageConnector =
|
const isInlineMenuButtonMessageConnector =
|
||||||
port.name === AutofillOverlayPort.ButtonMessageConnector;
|
port.name === AutofillOverlayPort.ButtonMessageConnector;
|
||||||
if (isOverlayListMessageConnector || isOverlayButtonMessageConnector) {
|
if (isInlineMenuListMessageConnector || isInlineMenuButtonMessageConnector) {
|
||||||
port.onMessage.addListener(this.handleOverlayElementPortMessage);
|
port.onMessage.addListener(this.handleOverlayElementPortMessage);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isOverlayListPort = port.name === AutofillOverlayPort.List;
|
const isInlineMenuListPort = port.name === AutofillOverlayPort.List;
|
||||||
const isOverlayButtonPort = port.name === AutofillOverlayPort.Button;
|
const isInlineMenuButtonPort = port.name === AutofillOverlayPort.Button;
|
||||||
if (!isOverlayListPort && !isOverlayButtonPort) {
|
if (!isInlineMenuListPort && !isInlineMenuButtonPort) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isOverlayListPort) {
|
if (isInlineMenuListPort) {
|
||||||
this.inlineMenuListPort = port;
|
this.inlineMenuListPort = port;
|
||||||
} else {
|
} else {
|
||||||
this.inlineMenuButtonPort = port;
|
this.inlineMenuButtonPort = port;
|
||||||
@@ -974,24 +975,26 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
|
|
||||||
port.onDisconnect.addListener(this.handlePortOnDisconnect);
|
port.onDisconnect.addListener(this.handlePortOnDisconnect);
|
||||||
port.postMessage({
|
port.postMessage({
|
||||||
command: `initAutofillOverlay${isOverlayListPort ? "List" : "Button"}`,
|
command: `initAutofillOverlay${isInlineMenuListPort ? "List" : "Button"}`,
|
||||||
iframeUrl: chrome.runtime.getURL(`overlay/${isOverlayListPort ? "list" : "button"}.html`),
|
iframeUrl: chrome.runtime.getURL(`overlay/${isInlineMenuListPort ? "list" : "button"}.html`),
|
||||||
pageTitle: chrome.i18n.getMessage(
|
pageTitle: chrome.i18n.getMessage(
|
||||||
isOverlayListPort ? "bitwardenVault" : "bitwardenOverlayButton",
|
isInlineMenuListPort ? "bitwardenVault" : "bitwardenOverlayButton",
|
||||||
),
|
),
|
||||||
authStatus: await this.getAuthStatus(),
|
authStatus: await this.getAuthStatus(),
|
||||||
styleSheetUrl: chrome.runtime.getURL(`overlay/${isOverlayListPort ? "list" : "button"}.css`),
|
styleSheetUrl: chrome.runtime.getURL(
|
||||||
|
`overlay/${isInlineMenuListPort ? "list" : "button"}.css`,
|
||||||
|
),
|
||||||
theme: await firstValueFrom(this.themeStateService.selectedTheme$),
|
theme: await firstValueFrom(this.themeStateService.selectedTheme$),
|
||||||
translations: this.getTranslations(),
|
translations: this.getInlineMenuTranslations(),
|
||||||
ciphers: isOverlayListPort ? await this.getOverlayCipherData() : null,
|
ciphers: isInlineMenuListPort ? await this.getOverlayCipherData() : null,
|
||||||
portKey: this.portKeyForTab[port.sender.tab.id],
|
portKey: this.portKeyForTab[port.sender.tab.id],
|
||||||
portName: isOverlayListPort
|
portName: isInlineMenuListPort
|
||||||
? AutofillOverlayPort.ListMessageConnector
|
? AutofillOverlayPort.ListMessageConnector
|
||||||
: AutofillOverlayPort.ButtonMessageConnector,
|
: AutofillOverlayPort.ButtonMessageConnector,
|
||||||
});
|
});
|
||||||
void this.updateInlineMenuPosition(
|
void this.updateInlineMenuPosition(
|
||||||
{
|
{
|
||||||
overlayElement: isOverlayListPort
|
overlayElement: isInlineMenuListPort
|
||||||
? AutofillOverlayElement.List
|
? AutofillOverlayElement.List
|
||||||
: AutofillOverlayElement.Button,
|
: AutofillOverlayElement.Button,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ type InitAutofillOverlayListMessage = OverlayListMessage & {
|
|||||||
type OverlayListWindowMessageHandlers = {
|
type OverlayListWindowMessageHandlers = {
|
||||||
[key: string]: CallableFunction;
|
[key: string]: CallableFunction;
|
||||||
initAutofillOverlayList: ({ message }: { message: InitAutofillOverlayListMessage }) => void;
|
initAutofillOverlayList: ({ message }: { message: InitAutofillOverlayListMessage }) => void;
|
||||||
checkAutofillOverlayListFocused: () => void;
|
checkAutofillInlineMenuListFocused: () => void;
|
||||||
updateOverlayListCiphers: ({ message }: { message: UpdateOverlayListCiphersMessage }) => void;
|
updateOverlayListCiphers: ({ message }: { message: UpdateOverlayListCiphersMessage }) => void;
|
||||||
focusInlineMenuList: () => void;
|
focusInlineMenuList: () => void;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ describe("AutofillOverlayList", () => {
|
|||||||
fillCipherButton.dispatchEvent(new Event("click"));
|
fillCipherButton.dispatchEvent(new Event("click"));
|
||||||
|
|
||||||
expect(globalThis.parent.postMessage).toHaveBeenCalledWith(
|
expect(globalThis.parent.postMessage).toHaveBeenCalledWith(
|
||||||
{ command: "fillSelectedListItem", overlayCipherId: "1", portKey },
|
{ command: "fillSelectedAutofillInlineMenuListItem", overlayCipherId: "1", portKey },
|
||||||
"*",
|
"*",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -292,7 +292,7 @@ describe("AutofillOverlayList", () => {
|
|||||||
it("does not post a `checkAutofillInlineMenuButtonFocused` message to the parent if the overlay is currently focused", () => {
|
it("does not post a `checkAutofillInlineMenuButtonFocused` message to the parent if the overlay is currently focused", () => {
|
||||||
jest.spyOn(globalThis.document, "hasFocus").mockReturnValue(true);
|
jest.spyOn(globalThis.document, "hasFocus").mockReturnValue(true);
|
||||||
|
|
||||||
postWindowMessage({ command: "checkAutofillOverlayListFocused" });
|
postWindowMessage({ command: "checkAutofillInlineMenuListFocused" });
|
||||||
|
|
||||||
expect(globalThis.parent.postMessage).not.toHaveBeenCalled();
|
expect(globalThis.parent.postMessage).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
@@ -300,7 +300,7 @@ describe("AutofillOverlayList", () => {
|
|||||||
it("posts a `checkAutofillInlineMenuButtonFocused` message to the parent if the overlay is not currently focused", () => {
|
it("posts a `checkAutofillInlineMenuButtonFocused` message to the parent if the overlay is not currently focused", () => {
|
||||||
jest.spyOn(globalThis.document, "hasFocus").mockReturnValue(false);
|
jest.spyOn(globalThis.document, "hasFocus").mockReturnValue(false);
|
||||||
|
|
||||||
postWindowMessage({ command: "checkAutofillOverlayListFocused" });
|
postWindowMessage({ command: "checkAutofillInlineMenuListFocused" });
|
||||||
|
|
||||||
expect(globalThis.parent.postMessage).toHaveBeenCalledWith(
|
expect(globalThis.parent.postMessage).toHaveBeenCalledWith(
|
||||||
{ command: "checkAutofillInlineMenuButtonFocused", portKey },
|
{ command: "checkAutofillInlineMenuButtonFocused", portKey },
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class AutofillOverlayList extends AutofillOverlayPageElement {
|
|||||||
private readonly showCiphersPerPage = 6;
|
private readonly showCiphersPerPage = 6;
|
||||||
private readonly overlayListWindowMessageHandlers: OverlayListWindowMessageHandlers = {
|
private readonly overlayListWindowMessageHandlers: OverlayListWindowMessageHandlers = {
|
||||||
initAutofillOverlayList: ({ message }) => this.initAutofillOverlayList(message),
|
initAutofillOverlayList: ({ message }) => this.initAutofillOverlayList(message),
|
||||||
checkAutofillOverlayListFocused: () => this.checkInlineMenuListFocused(),
|
checkAutofillInlineMenuListFocused: () => this.checkInlineMenuListFocused(),
|
||||||
updateOverlayListCiphers: ({ message }) => this.updateListItems(message.ciphers),
|
updateOverlayListCiphers: ({ message }) => this.updateListItems(message.ciphers),
|
||||||
focusInlineMenuList: () => this.focusInlineMenuList(),
|
focusInlineMenuList: () => this.focusInlineMenuList(),
|
||||||
};
|
};
|
||||||
@@ -279,7 +279,7 @@ class AutofillOverlayList extends AutofillOverlayPageElement {
|
|||||||
return this.useEventHandlersMemo(
|
return this.useEventHandlersMemo(
|
||||||
() =>
|
() =>
|
||||||
this.postMessageToParent({
|
this.postMessageToParent({
|
||||||
command: "fillSelectedListItem",
|
command: "fillSelectedAutofillInlineMenuListItem",
|
||||||
overlayCipherId: cipher.id,
|
overlayCipherId: cipher.id,
|
||||||
}),
|
}),
|
||||||
`${cipher.id}-fill-cipher-button-click-handler`,
|
`${cipher.id}-fill-cipher-button-click-handler`,
|
||||||
|
|||||||
Reference in New Issue
Block a user