1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-17 16:53:34 +00:00

[PM-5189] Refactoring implementation

This commit is contained in:
Cesar Gonzalez
2024-05-02 17:17:05 -05:00
parent b8ab84882d
commit 7355e63d0c
15 changed files with 239 additions and 220 deletions

View File

@@ -53,8 +53,8 @@ type OverlayBackgroundExtensionMessage = {
sender?: string; sender?: string;
details?: AutofillPageDetails; details?: AutofillPageDetails;
overlayElement?: string; overlayElement?: string;
forceCloseOverlay?: boolean; forceCloseAutofillInlineMenu?: boolean;
isOverlayHidden?: boolean; isAutofillInlineMenuHidden?: boolean;
setTransparentOverlay?: boolean; setTransparentOverlay?: boolean;
isFieldCurrentlyFocused?: boolean; isFieldCurrentlyFocused?: boolean;
isFieldCurrentlyFilling?: boolean; isFieldCurrentlyFilling?: boolean;
@@ -97,13 +97,13 @@ type OverlayBackgroundExtensionMessageHandlers = {
autofillOverlayElementClosed: ({ message }: BackgroundMessageParam) => void; autofillOverlayElementClosed: ({ message }: BackgroundMessageParam) => void;
autofillOverlayAddNewVaultItem: ({ message, sender }: BackgroundOnMessageHandlerParams) => void; autofillOverlayAddNewVaultItem: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
getInlineMenuVisibilitySetting: () => void; getInlineMenuVisibilitySetting: () => void;
checkAutofillOverlayMenuFocused: () => void; checkAutofillInlineMenuFocused: () => void;
focusAutofillOverlayMenuList: () => void; focusAutofillInlineMenuList: () => void;
updateAutofillOverlayMenuPosition: ({ updateAutofillInlineMenuPosition: ({
message, message,
sender, sender,
}: BackgroundOnMessageHandlerParams) => Promise<void>; }: BackgroundOnMessageHandlerParams) => Promise<void>;
updateAutofillOverlayMenuHidden: ({ message, sender }: BackgroundOnMessageHandlerParams) => void; updateAutofillInlineMenuHidden: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
updateFocusedFieldData: ({ message, sender }: BackgroundOnMessageHandlerParams) => void; updateFocusedFieldData: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
updateIsFieldCurrentlyFocused: ({ message }: BackgroundMessageParam) => void; updateIsFieldCurrentlyFocused: ({ message }: BackgroundMessageParam) => void;
checkIsFieldCurrentlyFocused: () => boolean; checkIsFieldCurrentlyFocused: () => boolean;
@@ -134,7 +134,7 @@ type OverlayButtonPortMessageHandlers = {
closeAutofillInlineMenu: ({ port }: PortConnectionParam) => void; closeAutofillInlineMenu: ({ port }: PortConnectionParam) => void;
forceCloseAutofillOverlay: ({ port }: PortConnectionParam) => void; forceCloseAutofillOverlay: ({ port }: PortConnectionParam) => void;
overlayPageBlurred: () => void; overlayPageBlurred: () => void;
redirectOverlayFocusOut: ({ message, port }: PortOnMessageHandlerParams) => void; redirectInlineMenuFocusOut: ({ message, port }: PortOnMessageHandlerParams) => void;
updateOverlayPageColorScheme: () => void; updateOverlayPageColorScheme: () => void;
}; };
@@ -147,7 +147,7 @@ type OverlayListPortMessageHandlers = {
fillSelectedListItem: ({ message, port }: PortOnMessageHandlerParams) => void; fillSelectedListItem: ({ message, port }: PortOnMessageHandlerParams) => void;
addNewVaultItem: ({ port }: PortConnectionParam) => void; addNewVaultItem: ({ port }: PortConnectionParam) => void;
viewSelectedCipher: ({ message, port }: PortOnMessageHandlerParams) => void; viewSelectedCipher: ({ message, port }: PortOnMessageHandlerParams) => void;
redirectOverlayFocusOut: ({ message, port }: PortOnMessageHandlerParams) => void; redirectInlineMenuFocusOut: ({ message, port }: PortOnMessageHandlerParams) => void;
updateAutofillOverlayListHeight: ({ message, port }: PortOnMessageHandlerParams) => void; updateAutofillOverlayListHeight: ({ message, port }: PortOnMessageHandlerParams) => void;
}; };

View File

@@ -564,7 +564,7 @@ describe("OverlayBackground", () => {
expect(BrowserApi.tabSendMessage).not.toHaveBeenCalledWith(sender.tab, { expect(BrowserApi.tabSendMessage).not.toHaveBeenCalledWith(sender.tab, {
command: "openAutofillInlineMenu", command: "openAutofillInlineMenu",
isFocusingFieldElement: false, isFocusingFieldElement: false,
isOpeningFullOverlay: false, isOpeningFullAutofillInlineMenu: false,
authStatus: AuthenticationStatus.Unlocked, authStatus: AuthenticationStatus.Unlocked,
}); });
}); });
@@ -668,13 +668,13 @@ describe("OverlayBackground", () => {
}); });
}); });
describe("checkAutofillOverlayMenuFocused message handler", () => { describe("checkAutofillInlineMenuFocused message handler", () => {
beforeEach(async () => { beforeEach(async () => {
await initOverlayElementPorts(); await initOverlayElementPorts();
}); });
it("will check if the overlay list is focused if the list port is open", () => { it("will check if the overlay list is focused if the list port is open", () => {
sendMockExtensionMessage({ command: "checkAutofillOverlayMenuFocused" }); sendMockExtensionMessage({ command: "checkAutofillInlineMenuFocused" });
expect(listPortSpy.postMessage).toHaveBeenCalledWith({ expect(listPortSpy.postMessage).toHaveBeenCalledWith({
command: "checkAutofillOverlayListFocused", command: "checkAutofillOverlayListFocused",
@@ -687,7 +687,7 @@ describe("OverlayBackground", () => {
it("will check if the overlay button is focused if the list port is not open", () => { it("will check if the overlay button is focused if the list port is not open", () => {
overlayBackground["overlayListPort"] = undefined; overlayBackground["overlayListPort"] = undefined;
sendMockExtensionMessage({ command: "checkAutofillOverlayMenuFocused" }); sendMockExtensionMessage({ command: "checkAutofillInlineMenuFocused" });
expect(buttonPortSpy.postMessage).toHaveBeenCalledWith({ expect(buttonPortSpy.postMessage).toHaveBeenCalledWith({
command: "checkAutofillOverlayButtonFocused", command: "checkAutofillOverlayButtonFocused",
@@ -698,8 +698,8 @@ describe("OverlayBackground", () => {
}); });
}); });
describe("focusAutofillOverlayMenuList message handler", () => { describe("focusAutofillInlineMenuList message handler", () => {
it("will send a `focusOverlayMenuList` message to the overlay list port", async () => { it("will send a `focusInlineMenuList` message to the overlay list port", async () => {
await initOverlayElementPorts({ await initOverlayElementPorts({
initList: true, initList: true,
initButton: false, initButton: false,
@@ -707,13 +707,13 @@ describe("OverlayBackground", () => {
initListMessageConnectorSpy: false, initListMessageConnectorSpy: false,
}); });
sendMockExtensionMessage({ command: "focusAutofillOverlayMenuList" }); sendMockExtensionMessage({ command: "focusAutofillInlineMenuList" });
expect(listPortSpy.postMessage).toHaveBeenCalledWith({ command: "focusOverlayMenuList" }); expect(listPortSpy.postMessage).toHaveBeenCalledWith({ command: "focusInlineMenuList" });
}); });
}); });
describe("updateAutofillOverlayMenuPosition message handler", () => { describe("updateAutofillInlineMenuPosition message handler", () => {
let sender: MockProxy<chrome.runtime.MessageSender>; let sender: MockProxy<chrome.runtime.MessageSender>;
beforeEach(async () => { beforeEach(async () => {
@@ -731,7 +731,7 @@ describe("OverlayBackground", () => {
}); });
it("ignores updating the position if the overlay element type is not provided", () => { it("ignores updating the position if the overlay element type is not provided", () => {
sendMockExtensionMessage({ command: "updateAutofillOverlayMenuPosition" }, sender); sendMockExtensionMessage({ command: "updateAutofillInlineMenuPosition" }, sender);
expect(listPortSpy.postMessage).not.toHaveBeenCalledWith({ expect(listPortSpy.postMessage).not.toHaveBeenCalledWith({
command: "updateIframePosition", command: "updateIframePosition",
@@ -749,7 +749,7 @@ describe("OverlayBackground", () => {
sendMockExtensionMessage( sendMockExtensionMessage(
{ {
command: "updateAutofillOverlayMenuPosition", command: "updateAutofillInlineMenuPosition",
overlayElement: AutofillOverlayElement.Button, overlayElement: AutofillOverlayElement.Button,
}, },
sender, sender,
@@ -770,7 +770,7 @@ describe("OverlayBackground", () => {
sendMockExtensionMessage( sendMockExtensionMessage(
{ {
command: "updateAutofillOverlayMenuPosition", command: "updateAutofillInlineMenuPosition",
overlayElement: AutofillOverlayElement.Button, overlayElement: AutofillOverlayElement.Button,
}, },
sender, sender,
@@ -791,7 +791,7 @@ describe("OverlayBackground", () => {
sendMockExtensionMessage( sendMockExtensionMessage(
{ {
command: "updateAutofillOverlayMenuPosition", command: "updateAutofillInlineMenuPosition",
overlayElement: AutofillOverlayElement.Button, overlayElement: AutofillOverlayElement.Button,
}, },
sender, sender,
@@ -812,7 +812,7 @@ describe("OverlayBackground", () => {
sendMockExtensionMessage( sendMockExtensionMessage(
{ {
command: "updateAutofillOverlayMenuPosition", command: "updateAutofillInlineMenuPosition",
overlayElement: AutofillOverlayElement.Button, overlayElement: AutofillOverlayElement.Button,
}, },
sender, sender,
@@ -831,7 +831,7 @@ describe("OverlayBackground", () => {
sendMockExtensionMessage( sendMockExtensionMessage(
{ {
command: "updateAutofillOverlayMenuPosition", command: "updateAutofillInlineMenuPosition",
overlayElement: AutofillOverlayElement.List, overlayElement: AutofillOverlayElement.List,
}, },
sender, sender,
@@ -851,7 +851,10 @@ describe("OverlayBackground", () => {
}); });
it("sets the `display` CSS value on the overlay button and list", () => { it("sets the `display` CSS value on the overlay button and list", () => {
const message = { command: "updateAutofillOverlayMenuHidden", isOverlayHidden: true }; const message = {
command: "updateAutofillInlineMenuHidden",
isAutofillInlineMenuHidden: true,
};
sendMockExtensionMessage(message); sendMockExtensionMessage(message);
@@ -871,7 +874,7 @@ describe("OverlayBackground", () => {
it("sets the `opacity` CSS value on the overlay button and list", () => { it("sets the `opacity` CSS value on the overlay button and list", () => {
const message = { const message = {
command: "updateAutofillOverlayMenuHidden", command: "updateAutofillInlineMenuHidden",
setTransparentOverlay: true, setTransparentOverlay: true,
}; };
@@ -998,7 +1001,7 @@ describe("OverlayBackground", () => {
{ {
command: "openAutofillInlineMenu", command: "openAutofillInlineMenu",
isFocusingFieldElement: true, isFocusingFieldElement: true,
isOpeningFullOverlay: false, isOpeningFullAutofillInlineMenu: false,
authStatus: AuthenticationStatus.Unlocked, authStatus: AuthenticationStatus.Unlocked,
}, },
{ frameId: 0 }, { frameId: 0 },
@@ -1036,7 +1039,7 @@ describe("OverlayBackground", () => {
describe("handlePortOnConnect", () => { describe("handlePortOnConnect", () => {
beforeEach(() => { beforeEach(() => {
jest.spyOn(overlayBackground as any, "updateOverlayMenuPosition").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, "getTranslations").mockImplementation();
jest.spyOn(overlayBackground as any, "getOverlayCipherData").mockImplementation(); jest.spyOn(overlayBackground as any, "getOverlayCipherData").mockImplementation();
@@ -1066,7 +1069,7 @@ describe("OverlayBackground", () => {
expect(chrome.runtime.getURL).toHaveBeenCalledWith("overlay/list.css"); expect(chrome.runtime.getURL).toHaveBeenCalledWith("overlay/list.css");
expect(overlayBackground["getTranslations"]).toHaveBeenCalled(); expect(overlayBackground["getTranslations"]).toHaveBeenCalled();
expect(overlayBackground["getOverlayCipherData"]).toHaveBeenCalled(); expect(overlayBackground["getOverlayCipherData"]).toHaveBeenCalled();
expect(overlayBackground["updateOverlayMenuPosition"]).toHaveBeenCalledWith( expect(overlayBackground["updateInlineMenuPosition"]).toHaveBeenCalledWith(
{ overlayElement: AutofillOverlayElement.List }, { overlayElement: AutofillOverlayElement.List },
listPortSpy.sender, listPortSpy.sender,
); );
@@ -1086,7 +1089,7 @@ describe("OverlayBackground", () => {
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["getTranslations"]).toHaveBeenCalled();
expect(overlayBackground["updateOverlayMenuPosition"]).toHaveBeenCalledWith( expect(overlayBackground["updateInlineMenuPosition"]).toHaveBeenCalledWith(
{ overlayElement: AutofillOverlayElement.Button }, { overlayElement: AutofillOverlayElement.Button },
buttonPortSpy.sender, buttonPortSpy.sender,
); );
@@ -1176,7 +1179,7 @@ describe("OverlayBackground", () => {
}); });
describe("forceCloseAutofillOverlay", () => { describe("forceCloseAutofillOverlay", () => {
it("sends a `closeOverlay` message to the sender tab with a `forceCloseOverlay` flag of `true` set", () => { it("sends a `closeOverlay` message to the sender tab with a `forceCloseAutofillInlineMenu` flag of `true` set", () => {
jest.spyOn(BrowserApi, "tabSendMessage"); jest.spyOn(BrowserApi, "tabSendMessage");
sendPortMessage(buttonMessageConnectorPortSpy, { sendPortMessage(buttonMessageConnectorPortSpy, {
@@ -1205,14 +1208,14 @@ describe("OverlayBackground", () => {
}); });
}); });
describe("redirectOverlayFocusOut", () => { describe("redirectInlineMenuFocusOut", () => {
beforeEach(() => { beforeEach(() => {
jest.spyOn(BrowserApi, "tabSendMessageData"); jest.spyOn(BrowserApi, "tabSendMessageData");
}); });
it("ignores the redirect message if the direction is not provided", () => { it("ignores the redirect message if the direction is not provided", () => {
sendPortMessage(buttonMessageConnectorPortSpy, { sendPortMessage(buttonMessageConnectorPortSpy, {
command: "redirectOverlayFocusOut", command: "redirectInlineMenuFocusOut",
portKey, portKey,
}); });
@@ -1221,14 +1224,14 @@ describe("OverlayBackground", () => {
it("sends the redirect message if the direction is provided", () => { it("sends the redirect message if the direction is provided", () => {
sendPortMessage(buttonMessageConnectorPortSpy, { sendPortMessage(buttonMessageConnectorPortSpy, {
command: "redirectOverlayFocusOut", command: "redirectInlineMenuFocusOut",
direction: RedirectFocusDirection.Next, direction: RedirectFocusDirection.Next,
portKey, portKey,
}); });
expect(BrowserApi.tabSendMessageData).toHaveBeenCalledWith( expect(BrowserApi.tabSendMessageData).toHaveBeenCalledWith(
buttonMessageConnectorPortSpy.sender.tab, buttonMessageConnectorPortSpy.sender.tab,
"redirectOverlayFocusOut", "redirectInlineMenuFocusOut",
{ direction: RedirectFocusDirection.Next }, { direction: RedirectFocusDirection.Next },
); );
}); });
@@ -1256,7 +1259,7 @@ describe("OverlayBackground", () => {
}); });
describe("forceCloseAutofillOverlay", () => { describe("forceCloseAutofillOverlay", () => {
it("sends a `closeOverlay` message to the sender tab with a `forceCloseOverlay` flag of `true` set", () => { it("sends a `closeOverlay` message to the sender tab with a `forceCloseAutofillInlineMenu` flag of `true` set", () => {
jest.spyOn(BrowserApi, "tabSendMessage"); jest.spyOn(BrowserApi, "tabSendMessage");
sendPortMessage(listMessageConnectorPortSpy, { sendPortMessage(listMessageConnectorPortSpy, {
@@ -1518,16 +1521,16 @@ describe("OverlayBackground", () => {
}); });
}); });
describe("redirectOverlayFocusOut", () => { describe("redirectInlineMenuFocusOut", () => {
it("redirects focus out of the overlay list", async () => { it("redirects focus out of the overlay list", async () => {
const message = { const message = {
command: "redirectOverlayFocusOut", command: "redirectInlineMenuFocusOut",
direction: RedirectFocusDirection.Next, direction: RedirectFocusDirection.Next,
portKey, portKey,
}; };
const redirectOverlayFocusOutSpy = jest.spyOn( const redirectOverlayFocusOutSpy = jest.spyOn(
overlayBackground as any, overlayBackground as any,
"redirectOverlayFocusOut", "redirectInlineMenuFocusOut",
); );
sendPortMessage(listMessageConnectorPortSpy, message); sendPortMessage(listMessageConnectorPortSpy, message);

View File

@@ -69,11 +69,11 @@ class OverlayBackground implements OverlayBackgroundInterface {
autofillOverlayElementClosed: ({ message }) => this.overlayElementClosed(message), autofillOverlayElementClosed: ({ message }) => this.overlayElementClosed(message),
autofillOverlayAddNewVaultItem: ({ message, sender }) => this.addNewVaultItem(message, sender), autofillOverlayAddNewVaultItem: ({ message, sender }) => this.addNewVaultItem(message, sender),
getInlineMenuVisibilitySetting: () => this.getInlineMenuVisibility(), getInlineMenuVisibilitySetting: () => this.getInlineMenuVisibility(),
checkAutofillOverlayMenuFocused: () => this.checkOverlayMenuFocused(), checkAutofillInlineMenuFocused: () => this.checkInlineMenuFocused(),
focusAutofillOverlayMenuList: () => this.focusOverlayMenuList(), focusAutofillInlineMenuList: () => this.focusInlineMenuList(),
updateAutofillOverlayMenuPosition: ({ message, sender }) => updateAutofillInlineMenuPosition: ({ message, sender }) =>
this.updateOverlayMenuPosition(message, sender), this.updateInlineMenuPosition(message, sender),
updateAutofillOverlayMenuHidden: ({ message, sender }) => updateAutofillInlineMenuHidden: ({ message, sender }) =>
this.updateOverlayMenuHidden(message, sender), this.updateOverlayMenuHidden(message, 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),
@@ -95,21 +95,23 @@ class OverlayBackground implements OverlayBackgroundInterface {
overlayButtonClicked: ({ port }) => this.handleOverlayButtonClicked(port), overlayButtonClicked: ({ port }) => this.handleOverlayButtonClicked(port),
closeAutofillInlineMenu: ({ port }) => this.closeInlineMenu(port.sender), closeAutofillInlineMenu: ({ port }) => this.closeInlineMenu(port.sender),
forceCloseAutofillOverlay: ({ port }) => forceCloseAutofillOverlay: ({ port }) =>
this.closeInlineMenu(port.sender, { forceCloseOverlay: true }), this.closeInlineMenu(port.sender, { forceCloseAutofillInlineMenu: true }),
overlayPageBlurred: () => this.checkOverlayListFocused(), overlayPageBlurred: () => this.checkOverlayListFocused(),
redirectOverlayFocusOut: ({ message, port }) => this.redirectOverlayFocusOut(message, port), redirectInlineMenuFocusOut: ({ message, port }) =>
this.redirectInlineMenuFocusOut(message, port),
updateOverlayPageColorScheme: () => this.updateButtonPageColorScheme(), updateOverlayPageColorScheme: () => this.updateButtonPageColorScheme(),
}; };
private readonly overlayListPortMessageHandlers: OverlayListPortMessageHandlers = { private readonly overlayListPortMessageHandlers: OverlayListPortMessageHandlers = {
checkAutofillOverlayButtonFocused: () => this.checkOverlayButtonFocused(), checkAutofillOverlayButtonFocused: () => this.checkOverlayButtonFocused(),
forceCloseAutofillOverlay: ({ port }) => forceCloseAutofillOverlay: ({ port }) =>
this.closeInlineMenu(port.sender, { forceCloseOverlay: true }), this.closeInlineMenu(port.sender, { forceCloseAutofillInlineMenu: true }),
overlayPageBlurred: () => this.checkOverlayButtonFocused(), overlayPageBlurred: () => this.checkOverlayButtonFocused(),
unlockVault: ({ port }) => this.unlockVault(port), unlockVault: ({ port }) => this.unlockVault(port),
fillSelectedListItem: ({ message, port }) => this.fillSelectedOverlayListItem(message, port), fillSelectedListItem: ({ message, port }) => this.fillSelectedOverlayListItem(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),
redirectOverlayFocusOut: ({ message, port }) => this.redirectOverlayFocusOut(message, port), redirectInlineMenuFocusOut: ({ message, port }) =>
this.redirectInlineMenuFocusOut(message, port),
updateAutofillOverlayListHeight: ({ message }) => this.updateOverlayListHeight(message), updateAutofillOverlayListHeight: ({ message }) => this.updateOverlayListHeight(message),
}; };
@@ -333,11 +335,8 @@ class OverlayBackground implements OverlayBackgroundInterface {
this.updateOverlayMenuPositionTimeout = setTimeout(() => { this.updateOverlayMenuPositionTimeout = setTimeout(() => {
if (this.isFieldCurrentlyFocused) { if (this.isFieldCurrentlyFocused) {
void this.updateOverlayMenuPosition( void this.updateInlineMenuPosition({ overlayElement: AutofillOverlayElement.List }, sender);
{ overlayElement: AutofillOverlayElement.List }, void this.updateInlineMenuPosition(
sender,
);
void this.updateOverlayMenuPosition(
{ overlayElement: AutofillOverlayElement.Button }, { overlayElement: AutofillOverlayElement.Button },
sender, sender,
); );
@@ -385,7 +384,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
* Checks if the overlay is focused. Will check the overlay list * Checks if the overlay is focused. Will check the overlay list
* if it is open, otherwise it will check the overlay button. * if it is open, otherwise it will check the overlay button.
*/ */
private checkOverlayMenuFocused() { private checkInlineMenuFocused() {
if (this.overlayListPort) { if (this.overlayListPort) {
this.checkOverlayListFocused(); this.checkOverlayListFocused();
@@ -413,17 +412,17 @@ class OverlayBackground implements OverlayBackgroundInterface {
* Sends a message to the sender tab to close the autofill overlay. * Sends a message to the sender tab to close the autofill overlay.
* *
* @param sender - The sender of the port message * @param sender - The sender of the port message
* @param forceCloseOverlay - Identifies whether the overlay should be forced closed * @param forceCloseAutofillInlineMenu - Identifies whether the overlay 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(
sender: chrome.runtime.MessageSender, sender: chrome.runtime.MessageSender,
{ {
forceCloseOverlay, forceCloseAutofillInlineMenu,
overlayElement, overlayElement,
}: { forceCloseOverlay?: boolean; overlayElement?: string } = {}, }: { forceCloseAutofillInlineMenu?: boolean; overlayElement?: string } = {},
) { ) {
if (forceCloseOverlay) { if (forceCloseAutofillInlineMenu) {
void BrowserApi.tabSendMessage( void BrowserApi.tabSendMessage(
sender.tab, sender.tab,
{ command: "closeInlineMenu", overlayElement }, { command: "closeInlineMenu", overlayElement },
@@ -480,7 +479,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
* @param overlayElement - The overlay element to update, either the list or button * @param overlayElement - The overlay element to update, either the list or button
* @param sender - The sender of the extension message * @param sender - The sender of the extension message
*/ */
private async updateOverlayMenuPosition( private async updateInlineMenuPosition(
{ overlayElement }: { overlayElement?: string }, { overlayElement }: { overlayElement?: string },
sender: chrome.runtime.MessageSender, sender: chrome.runtime.MessageSender,
) { ) {
@@ -592,10 +591,10 @@ class OverlayBackground implements OverlayBackgroundInterface {
* @param sender - The sender of the extension message * @param sender - The sender of the extension message
*/ */
private updateOverlayMenuHidden( private updateOverlayMenuHidden(
{ isOverlayHidden, setTransparentOverlay }: OverlayBackgroundExtensionMessage, { isAutofillInlineMenuHidden, setTransparentOverlay }: OverlayBackgroundExtensionMessage,
sender: chrome.runtime.MessageSender, sender: chrome.runtime.MessageSender,
) { ) {
const display = isOverlayHidden ? "none" : "block"; const display = isAutofillInlineMenuHidden ? "none" : "block";
let styles: { display: string; opacity?: number } = { display }; let styles: { display: string; opacity?: number } = { display };
if (typeof setTransparentOverlay !== "undefined") { if (typeof setTransparentOverlay !== "undefined") {
@@ -607,7 +606,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
void BrowserApi.tabSendMessage( void BrowserApi.tabSendMessage(
sender.tab, sender.tab,
{ command: "toggleInlineMenuHidden", isInlineMenuHidden: isOverlayHidden }, { command: "toggleInlineMenuHidden", isInlineMenuHidden: isAutofillInlineMenuHidden },
{ frameId: 0 }, { frameId: 0 },
); );
@@ -619,9 +618,12 @@ 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 overlay.
* *
* @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 overlay is opened
* @param isOpeningFullOverlay - Identifies whether the full overlay should be forced open regardless of other states * @param isOpeningFullAutofillInlineMenu - Identifies whether the full overlay should be forced open regardless of other states
*/ */
private async openInlineMenu(isFocusingFieldElement = false, isOpeningFullOverlay = false) { private async openInlineMenu(
isFocusingFieldElement = false,
isOpeningFullAutofillInlineMenu = false,
) {
const currentTab = await BrowserApi.getTabFromCurrentWindowId(); const currentTab = await BrowserApi.getTabFromCurrentWindowId();
await BrowserApi.tabSendMessage( await BrowserApi.tabSendMessage(
@@ -629,7 +631,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
{ {
command: "openAutofillInlineMenu", command: "openAutofillInlineMenu",
isFocusingFieldElement, isFocusingFieldElement,
isOpeningFullOverlay, isOpeningFullAutofillInlineMenu,
authStatus: await this.getAuthStatus(), authStatus: await this.getAuthStatus(),
}, },
{ {
@@ -736,8 +738,8 @@ class OverlayBackground implements OverlayBackgroundInterface {
/** /**
* Facilitates redirecting focus to the overlay list. * Facilitates redirecting focus to the overlay list.
*/ */
private focusOverlayMenuList() { private focusInlineMenuList() {
this.overlayListPort?.postMessage({ command: "focusOverlayMenuList" }); this.overlayListPort?.postMessage({ command: "focusInlineMenuList" });
} }
/** /**
@@ -786,7 +788,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
* @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
*/ */
private redirectOverlayFocusOut( private redirectInlineMenuFocusOut(
{ direction }: OverlayPortMessage, { direction }: OverlayPortMessage,
{ sender }: chrome.runtime.Port, { sender }: chrome.runtime.Port,
) { ) {
@@ -794,7 +796,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
return; return;
} }
void BrowserApi.tabSendMessageData(sender.tab, "redirectOverlayFocusOut", { direction }); void BrowserApi.tabSendMessageData(sender.tab, "redirectInlineMenuFocusOut", { direction });
} }
/** /**
@@ -983,7 +985,7 @@ class OverlayBackground implements OverlayBackgroundInterface {
? AutofillOverlayPort.ListMessageConnector ? AutofillOverlayPort.ListMessageConnector
: AutofillOverlayPort.ButtonMessageConnector, : AutofillOverlayPort.ButtonMessageConnector,
}); });
void this.updateOverlayMenuPosition( void this.updateInlineMenuPosition(
{ {
overlayElement: isOverlayListPort overlayElement: isOverlayListPort
? AutofillOverlayElement.List ? AutofillOverlayElement.List

View File

@@ -16,11 +16,11 @@ export type AutofillExtensionMessage = {
overlayElement?: string; overlayElement?: string;
isFocusingFieldElement?: boolean; isFocusingFieldElement?: boolean;
authStatus?: AuthenticationStatus; authStatus?: AuthenticationStatus;
isOpeningFullOverlay?: boolean; isOpeningFullAutofillInlineMenu?: boolean;
data?: { data?: {
isOverlayCiphersPopulated?: boolean; isOverlayCiphersPopulated?: boolean;
direction?: "previous" | "next" | "current"; direction?: "previous" | "next" | "current";
forceCloseOverlay?: boolean; forceCloseAutofillInlineMenu?: boolean;
inlineMenuVisibility?: number; inlineMenuVisibility?: number;
}; };
}; };

View File

@@ -22,7 +22,7 @@ type OverlayListWindowMessageHandlers = {
initAutofillOverlayList: ({ message }: { message: InitAutofillOverlayListMessage }) => void; initAutofillOverlayList: ({ message }: { message: InitAutofillOverlayListMessage }) => void;
checkAutofillOverlayListFocused: () => void; checkAutofillOverlayListFocused: () => void;
updateOverlayListCiphers: ({ message }: { message: UpdateOverlayListCiphersMessage }) => void; updateOverlayListCiphers: ({ message }: { message: UpdateOverlayListCiphersMessage }) => void;
focusOverlayMenuList: () => void; focusInlineMenuList: () => void;
}; };
export { export {

View File

@@ -330,7 +330,7 @@ describe("AutofillOverlayList", () => {
"setAttribute", "setAttribute",
); );
postWindowMessage({ command: "focusOverlayMenuList" }); postWindowMessage({ command: "focusInlineMenuList" });
expect(overlayContainerSetAttributeSpy).toHaveBeenCalledWith("role", "dialog"); expect(overlayContainerSetAttributeSpy).toHaveBeenCalledWith("role", "dialog");
expect(overlayContainerSetAttributeSpy).toHaveBeenCalledWith("aria-modal", "true"); expect(overlayContainerSetAttributeSpy).toHaveBeenCalledWith("aria-modal", "true");
@@ -348,7 +348,7 @@ describe("AutofillOverlayList", () => {
autofillOverlayList["overlayListContainer"].querySelector("#unlock-button"); autofillOverlayList["overlayListContainer"].querySelector("#unlock-button");
jest.spyOn(unlockButton as HTMLElement, "focus"); jest.spyOn(unlockButton as HTMLElement, "focus");
postWindowMessage({ command: "focusOverlayMenuList" }); postWindowMessage({ command: "focusInlineMenuList" });
expect((unlockButton as HTMLElement).focus).toBeCalled(); expect((unlockButton as HTMLElement).focus).toBeCalled();
}); });
@@ -360,7 +360,7 @@ describe("AutofillOverlayList", () => {
autofillOverlayList["overlayListContainer"].querySelector("#new-item-button"); autofillOverlayList["overlayListContainer"].querySelector("#new-item-button");
jest.spyOn(newItemButton as HTMLElement, "focus"); jest.spyOn(newItemButton as HTMLElement, "focus");
postWindowMessage({ command: "focusOverlayMenuList" }); postWindowMessage({ command: "focusInlineMenuList" });
expect((newItemButton as HTMLElement).focus).toBeCalled(); expect((newItemButton as HTMLElement).focus).toBeCalled();
}); });
@@ -371,7 +371,7 @@ describe("AutofillOverlayList", () => {
autofillOverlayList["overlayListContainer"].querySelector(".fill-cipher-button"); autofillOverlayList["overlayListContainer"].querySelector(".fill-cipher-button");
jest.spyOn(firstCipherItem as HTMLElement, "focus"); jest.spyOn(firstCipherItem as HTMLElement, "focus");
postWindowMessage({ command: "focusOverlayMenuList" }); postWindowMessage({ command: "focusInlineMenuList" });
expect((firstCipherItem as HTMLElement).focus).toBeCalled(); expect((firstCipherItem as HTMLElement).focus).toBeCalled();
}); });
@@ -407,7 +407,7 @@ describe("AutofillOverlayList", () => {
); );
expect(globalThis.parent.postMessage).toHaveBeenCalledWith( expect(globalThis.parent.postMessage).toHaveBeenCalledWith(
{ command: "redirectOverlayFocusOut", direction: "previous", portKey }, { command: "redirectInlineMenuFocusOut", direction: "previous", portKey },
"*", "*",
); );
}); });
@@ -416,7 +416,7 @@ describe("AutofillOverlayList", () => {
globalThis.document.dispatchEvent(new KeyboardEvent("keydown", { code: "Tab" })); globalThis.document.dispatchEvent(new KeyboardEvent("keydown", { code: "Tab" }));
expect(globalThis.parent.postMessage).toHaveBeenCalledWith( expect(globalThis.parent.postMessage).toHaveBeenCalledWith(
{ command: "redirectOverlayFocusOut", direction: "next", portKey }, { command: "redirectInlineMenuFocusOut", direction: "next", portKey },
"*", "*",
); );
}); });
@@ -425,7 +425,7 @@ describe("AutofillOverlayList", () => {
globalThis.document.dispatchEvent(new KeyboardEvent("keydown", { code: "Escape" })); globalThis.document.dispatchEvent(new KeyboardEvent("keydown", { code: "Escape" }));
expect(globalThis.parent.postMessage).toHaveBeenCalledWith( expect(globalThis.parent.postMessage).toHaveBeenCalledWith(
{ command: "redirectOverlayFocusOut", direction: "current", portKey }, { command: "redirectInlineMenuFocusOut", direction: "current", portKey },
"*", "*",
); );
}); });

View File

@@ -26,7 +26,7 @@ class AutofillOverlayList extends AutofillOverlayPageElement {
initAutofillOverlayList: ({ message }) => this.initAutofillOverlayList(message), initAutofillOverlayList: ({ message }) => this.initAutofillOverlayList(message),
checkAutofillOverlayListFocused: () => this.checkOverlayListFocused(), checkAutofillOverlayListFocused: () => this.checkOverlayListFocused(),
updateOverlayListCiphers: ({ message }) => this.updateListItems(message.ciphers), updateOverlayListCiphers: ({ message }) => this.updateListItems(message.ciphers),
focusOverlayMenuList: () => this.focusOverlayMenuList(), focusInlineMenuList: () => this.focusInlineMenuList(),
}; };
constructor() { constructor() {
@@ -495,7 +495,7 @@ class AutofillOverlayList extends AutofillOverlayPageElement {
* determined by the presence of the unlock button, new item button, or * determined by the presence of the unlock button, new item button, or
* the first cipher button. * the first cipher button.
*/ */
private focusOverlayMenuList() { private focusInlineMenuList() {
this.overlayListContainer.setAttribute("role", "dialog"); this.overlayListContainer.setAttribute("role", "dialog");
this.overlayListContainer.setAttribute("aria-modal", "true"); this.overlayListContainer.setAttribute("aria-modal", "true");

View File

@@ -150,7 +150,7 @@ class AutofillOverlayPageElement extends HTMLElement {
* @param direction - The direction to redirect the focus out * @param direction - The direction to redirect the focus out
*/ */
private redirectOverlayFocusOutMessage(direction: string) { private redirectOverlayFocusOutMessage(direction: string) {
this.postMessageToParent({ command: "redirectOverlayFocusOut", direction }); this.postMessageToParent({ command: "redirectInlineMenuFocusOut", direction });
} }
} }

View File

@@ -5,9 +5,9 @@ import { AutofillExtensionMessageParam } from "../../content/abstractions/autofi
import AutofillField from "../../models/autofill-field"; import AutofillField from "../../models/autofill-field";
import { ElementWithOpId, FormFieldElement } from "../../types"; import { ElementWithOpId, FormFieldElement } from "../../types";
export type OpenAutofillOverlayOptions = { export type OpenAutofillInlineMenuOptions = {
isFocusingFieldElement?: boolean; isFocusingFieldElement?: boolean;
isOpeningFullOverlay?: boolean; isOpeningFullAutofillInlineMenu?: boolean;
authStatus?: AuthenticationStatus; authStatus?: AuthenticationStatus;
}; };
@@ -18,8 +18,8 @@ export type AutofillOverlayContentExtensionMessageHandlers = {
blurMostRecentOverlayField: () => void; blurMostRecentOverlayField: () => void;
bgUnlockPopoutOpened: () => void; bgUnlockPopoutOpened: () => void;
bgVaultItemRepromptPopoutOpened: () => void; bgVaultItemRepromptPopoutOpened: () => void;
redirectOverlayFocusOut: ({ message }: AutofillExtensionMessageParam) => void; redirectInlineMenuFocusOut: ({ message }: AutofillExtensionMessageParam) => void;
updateInlineMenuVisibility: ({ message }: AutofillExtensionMessageParam) => void; updateAutofillInlineMenuVisibility: ({ message }: AutofillExtensionMessageParam) => void;
getSubFrameOffsets: ({ message }: AutofillExtensionMessageParam) => Promise<SubFrameOffsetData>; getSubFrameOffsets: ({ message }: AutofillExtensionMessageParam) => Promise<SubFrameOffsetData>;
getSubFrameOffsetsFromWindowMessage: ({ message }: AutofillExtensionMessageParam) => void; getSubFrameOffsetsFromWindowMessage: ({ message }: AutofillExtensionMessageParam) => void;
}; };
@@ -28,7 +28,7 @@ export interface AutofillOverlayContentService {
pageDetailsUpdateRequired: boolean; pageDetailsUpdateRequired: boolean;
extensionMessageHandlers: AutofillOverlayContentExtensionMessageHandlers; extensionMessageHandlers: AutofillOverlayContentExtensionMessageHandlers;
init(): void; init(): void;
setupAutofillOverlayListenerOnField( setupAutofillInlineMenuListenerOnField(
autofillFieldElement: ElementWithOpId<FormFieldElement>, autofillFieldElement: ElementWithOpId<FormFieldElement>,
autofillFieldData: AutofillField, autofillFieldData: AutofillField,
): Promise<void>; ): Promise<void>;

View File

@@ -98,7 +98,7 @@ describe("AutofillOverlayContentService", () => {
}); });
}); });
describe("setupAutofillOverlayListenerOnField", () => { describe("setupAutofillInlineMenuListenerOnField", () => {
let autofillFieldElement: ElementWithOpId<FormFieldElement>; let autofillFieldElement: ElementWithOpId<FormFieldElement>;
let autofillFieldData: AutofillField; let autofillFieldData: AutofillField;
@@ -131,7 +131,7 @@ describe("AutofillOverlayContentService", () => {
it("ignores fields that are readonly", async () => { it("ignores fields that are readonly", async () => {
autofillFieldData.readonly = true; autofillFieldData.readonly = true;
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -142,7 +142,7 @@ describe("AutofillOverlayContentService", () => {
it("ignores fields that contain a disabled attribute", async () => { it("ignores fields that contain a disabled attribute", async () => {
autofillFieldData.disabled = true; autofillFieldData.disabled = true;
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -153,7 +153,7 @@ describe("AutofillOverlayContentService", () => {
it("ignores fields that are not viewable", async () => { it("ignores fields that are not viewable", async () => {
autofillFieldData.viewable = false; autofillFieldData.viewable = false;
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -165,7 +165,7 @@ describe("AutofillOverlayContentService", () => {
AutoFillConstants.ExcludedOverlayTypes.forEach(async (excludedType) => { AutoFillConstants.ExcludedOverlayTypes.forEach(async (excludedType) => {
autofillFieldData.type = excludedType; autofillFieldData.type = excludedType;
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -177,7 +177,7 @@ describe("AutofillOverlayContentService", () => {
it("ignores fields that contain the keyword `search`", async () => { it("ignores fields that contain the keyword `search`", async () => {
autofillFieldData.placeholder = "search"; autofillFieldData.placeholder = "search";
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -188,7 +188,7 @@ describe("AutofillOverlayContentService", () => {
it("ignores fields that contain the keyword `captcha` ", async () => { it("ignores fields that contain the keyword `captcha` ", async () => {
autofillFieldData.placeholder = "captcha"; autofillFieldData.placeholder = "captcha";
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -200,7 +200,7 @@ describe("AutofillOverlayContentService", () => {
it.skip("ignores fields that do not appear as a login field", async () => { it.skip("ignores fields that do not appear as a login field", async () => {
autofillFieldData.placeholder = "not-a-login-field"; autofillFieldData.placeholder = "not-a-login-field";
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -212,7 +212,7 @@ describe("AutofillOverlayContentService", () => {
it("skips setup on fields that have been previously set up", async () => { it("skips setup on fields that have been previously set up", async () => {
autofillOverlayContentService["formFieldElements"].add(autofillFieldElement); autofillOverlayContentService["formFieldElements"].add(autofillFieldElement);
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -225,7 +225,7 @@ describe("AutofillOverlayContentService", () => {
sendExtensionMessageSpy.mockResolvedValueOnce(undefined); sendExtensionMessageSpy.mockResolvedValueOnce(undefined);
autofillOverlayContentService["inlineMenuVisibility"] = undefined; autofillOverlayContentService["inlineMenuVisibility"] = undefined;
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -240,7 +240,7 @@ describe("AutofillOverlayContentService", () => {
sendExtensionMessageSpy.mockResolvedValueOnce(AutofillOverlayVisibility.OnFieldFocus); sendExtensionMessageSpy.mockResolvedValueOnce(AutofillOverlayVisibility.OnFieldFocus);
autofillOverlayContentService["inlineMenuVisibility"] = undefined; autofillOverlayContentService["inlineMenuVisibility"] = undefined;
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -264,7 +264,7 @@ describe("AutofillOverlayContentService", () => {
"op-1-username-field-focus-handler": focusHandler, "op-1-username-field-focus-handler": focusHandler,
}; };
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -288,7 +288,7 @@ describe("AutofillOverlayContentService", () => {
describe("form field blur event listener", () => { describe("form field blur event listener", () => {
beforeEach(async () => { beforeEach(async () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -305,13 +305,13 @@ describe("AutofillOverlayContentService", () => {
it("sends a message to the background to check if the overlay is focused", () => { it("sends a message to the background to check if the overlay is focused", () => {
autofillFieldElement.dispatchEvent(new Event("blur")); autofillFieldElement.dispatchEvent(new Event("blur"));
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("checkAutofillOverlayMenuFocused"); expect(sendExtensionMessageSpy).toHaveBeenCalledWith("checkAutofillInlineMenuFocused");
}); });
}); });
describe("form field keyup event listener", () => { describe("form field keyup event listener", () => {
beforeEach(async () => { beforeEach(async () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -322,7 +322,7 @@ describe("AutofillOverlayContentService", () => {
autofillFieldElement.dispatchEvent(new KeyboardEvent("keyup", { code: "Escape" })); autofillFieldElement.dispatchEvent(new KeyboardEvent("keyup", { code: "Escape" }));
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu", { expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu", {
forceCloseOverlay: true, forceCloseAutofillInlineMenu: true,
}); });
}); });
@@ -374,12 +374,14 @@ describe("AutofillOverlayContentService", () => {
await flushPromises(); await flushPromises();
expect(updateMostRecentlyFocusedFieldSpy).toHaveBeenCalledWith(autofillFieldElement); expect(updateMostRecentlyFocusedFieldSpy).toHaveBeenCalledWith(autofillFieldElement);
expect(openAutofillOverlaySpy).toHaveBeenCalledWith({ isOpeningFullOverlay: true }); expect(openAutofillOverlaySpy).toHaveBeenCalledWith({
expect(sendExtensionMessageSpy).not.toHaveBeenCalledWith("focusAutofillOverlayMenuList"); isOpeningFullAutofillInlineMenu: true,
});
expect(sendExtensionMessageSpy).not.toHaveBeenCalledWith("focusAutofillInlineMenuList");
jest.advanceTimersByTime(150); jest.advanceTimersByTime(150);
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("focusAutofillOverlayMenuList"); expect(sendExtensionMessageSpy).toHaveBeenCalledWith("focusAutofillInlineMenuList");
}); });
it("focuses the overlay list when the `ArrowDown` key is pressed", async () => { it("focuses the overlay list when the `ArrowDown` key is pressed", async () => {
@@ -390,7 +392,7 @@ describe("AutofillOverlayContentService", () => {
autofillFieldElement.dispatchEvent(new KeyboardEvent("keyup", { code: "ArrowDown" })); autofillFieldElement.dispatchEvent(new KeyboardEvent("keyup", { code: "ArrowDown" }));
await flushPromises(); await flushPromises();
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("focusAutofillOverlayMenuList"); expect(sendExtensionMessageSpy).toHaveBeenCalledWith("focusAutofillInlineMenuList");
}); });
}); });
@@ -405,7 +407,7 @@ describe("AutofillOverlayContentService", () => {
) as ElementWithOpId<HTMLSpanElement>; ) as ElementWithOpId<HTMLSpanElement>;
jest.spyOn(autofillOverlayContentService as any, "storeModifiedFormElement"); jest.spyOn(autofillOverlayContentService as any, "storeModifiedFormElement");
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
spanAutofillFieldElement, spanAutofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -416,7 +418,7 @@ describe("AutofillOverlayContentService", () => {
}); });
it("stores the field as a user filled field if the form field data indicates that it is for a username", async () => { it("stores the field as a user filled field if the form field data indicates that it is for a username", async () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -432,7 +434,7 @@ describe("AutofillOverlayContentService", () => {
"password-field", "password-field",
) as ElementWithOpId<FormFieldElement>; ) as ElementWithOpId<FormFieldElement>;
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
passwordFieldElement, passwordFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -447,7 +449,7 @@ describe("AutofillOverlayContentService", () => {
jest.spyOn(autofillOverlayContentService as any, "isUserAuthed").mockReturnValue(false); jest.spyOn(autofillOverlayContentService as any, "isUserAuthed").mockReturnValue(false);
(autofillFieldElement as HTMLInputElement).value = "test"; (autofillFieldElement as HTMLInputElement).value = "test";
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -456,7 +458,7 @@ describe("AutofillOverlayContentService", () => {
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu", { expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu", {
overlayElement: AutofillOverlayElement.List, overlayElement: AutofillOverlayElement.List,
forceCloseOverlay: true, forceCloseAutofillInlineMenu: true,
}); });
}); });
@@ -468,7 +470,7 @@ describe("AutofillOverlayContentService", () => {
(autofillFieldElement as HTMLInputElement).value = "test"; (autofillFieldElement as HTMLInputElement).value = "test";
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -477,7 +479,7 @@ describe("AutofillOverlayContentService", () => {
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu", { expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu", {
overlayElement: AutofillOverlayElement.List, overlayElement: AutofillOverlayElement.List,
forceCloseOverlay: true, forceCloseAutofillInlineMenu: true,
}); });
}); });
@@ -485,7 +487,7 @@ describe("AutofillOverlayContentService", () => {
jest.spyOn(autofillOverlayContentService as any, "openAutofillInlineMenu"); jest.spyOn(autofillOverlayContentService as any, "openAutofillInlineMenu");
(autofillFieldElement as HTMLInputElement).value = ""; (autofillFieldElement as HTMLInputElement).value = "";
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -500,7 +502,7 @@ describe("AutofillOverlayContentService", () => {
jest.spyOn(autofillOverlayContentService as any, "openAutofillInlineMenu"); jest.spyOn(autofillOverlayContentService as any, "openAutofillInlineMenu");
(autofillFieldElement as HTMLInputElement).value = ""; (autofillFieldElement as HTMLInputElement).value = "";
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -518,7 +520,7 @@ describe("AutofillOverlayContentService", () => {
jest.spyOn(autofillOverlayContentService as any, "openAutofillInlineMenu"); jest.spyOn(autofillOverlayContentService as any, "openAutofillInlineMenu");
(autofillFieldElement as HTMLInputElement).value = ""; (autofillFieldElement as HTMLInputElement).value = "";
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -542,7 +544,7 @@ describe("AutofillOverlayContentService", () => {
jest jest
.spyOn(autofillOverlayContentService as any, "isInlineMenuListVisible") .spyOn(autofillOverlayContentService as any, "isInlineMenuListVisible")
.mockResolvedValue(false); .mockResolvedValue(false);
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -596,7 +598,7 @@ describe("AutofillOverlayContentService", () => {
autofillOverlayContentService["mostRecentlyFocusedField"] = autofillFieldElement; autofillOverlayContentService["mostRecentlyFocusedField"] = autofillFieldElement;
autofillOverlayContentService["inlineMenuVisibility"] = autofillOverlayContentService["inlineMenuVisibility"] =
AutofillOverlayVisibility.OnFieldFocus; AutofillOverlayVisibility.OnFieldFocus;
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -608,7 +610,7 @@ describe("AutofillOverlayContentService", () => {
}); });
it("updates the most recently focused field", async () => { it("updates the most recently focused field", async () => {
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -625,7 +627,7 @@ describe("AutofillOverlayContentService", () => {
it("removes the overlay list if the autofill visibility is set to onClick", async () => { it("removes the overlay list if the autofill visibility is set to onClick", async () => {
autofillOverlayContentService["inlineMenuVisibility"] = autofillOverlayContentService["inlineMenuVisibility"] =
AutofillOverlayVisibility.OnButtonClick; AutofillOverlayVisibility.OnButtonClick;
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -635,7 +637,7 @@ describe("AutofillOverlayContentService", () => {
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu", { expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu", {
overlayElement: AutofillOverlayElement.List, overlayElement: AutofillOverlayElement.List,
forceCloseOverlay: true, forceCloseAutofillInlineMenu: true,
}); });
}); });
@@ -644,7 +646,7 @@ describe("AutofillOverlayContentService", () => {
"input", "input",
) as ElementWithOpId<HTMLInputElement>; ) as ElementWithOpId<HTMLInputElement>;
(autofillFieldElement as HTMLInputElement).value = "test"; (autofillFieldElement as HTMLInputElement).value = "test";
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -654,7 +656,7 @@ describe("AutofillOverlayContentService", () => {
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu", { expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu", {
overlayElement: AutofillOverlayElement.List, overlayElement: AutofillOverlayElement.List,
forceCloseOverlay: true, forceCloseAutofillInlineMenu: true,
}); });
}); });
@@ -662,7 +664,7 @@ describe("AutofillOverlayContentService", () => {
(autofillFieldElement as HTMLInputElement).value = ""; (autofillFieldElement as HTMLInputElement).value = "";
autofillOverlayContentService["inlineMenuVisibility"] = autofillOverlayContentService["inlineMenuVisibility"] =
AutofillOverlayVisibility.OnFieldFocus; AutofillOverlayVisibility.OnFieldFocus;
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -678,7 +680,7 @@ describe("AutofillOverlayContentService", () => {
autofillOverlayContentService["inlineMenuVisibility"] = autofillOverlayContentService["inlineMenuVisibility"] =
AutofillOverlayVisibility.OnFieldFocus; AutofillOverlayVisibility.OnFieldFocus;
jest.spyOn(autofillOverlayContentService as any, "isUserAuthed").mockReturnValue(true); jest.spyOn(autofillOverlayContentService as any, "isUserAuthed").mockReturnValue(true);
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -696,7 +698,7 @@ describe("AutofillOverlayContentService", () => {
jest jest
.spyOn(autofillOverlayContentService as any, "isInlineMenuCiphersPopulated") .spyOn(autofillOverlayContentService as any, "isInlineMenuCiphersPopulated")
.mockReturnValue(true); .mockReturnValue(true);
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -704,12 +706,9 @@ describe("AutofillOverlayContentService", () => {
autofillFieldElement.dispatchEvent(new Event("focus")); autofillFieldElement.dispatchEvent(new Event("focus"));
await flushPromises(); await flushPromises();
expect(sendExtensionMessageSpy).toHaveBeenCalledWith( expect(sendExtensionMessageSpy).toHaveBeenCalledWith("updateAutofillInlineMenuPosition", {
"updateAutofillOverlayMenuPosition", overlayElement: AutofillOverlayElement.Button,
{ });
overlayElement: AutofillOverlayElement.Button,
},
);
}); });
}); });
}); });
@@ -721,7 +720,7 @@ describe("AutofillOverlayContentService", () => {
writable: true, writable: true,
}); });
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -735,7 +734,7 @@ describe("AutofillOverlayContentService", () => {
it("sets the most recently focused field to the passed form field element if the value is not set", async () => { it("sets the most recently focused field to the passed form field element if the value is not set", async () => {
autofillOverlayContentService["mostRecentlyFocusedField"] = undefined; autofillOverlayContentService["mostRecentlyFocusedField"] = undefined;
await autofillOverlayContentService.setupAutofillOverlayListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );
@@ -819,10 +818,10 @@ describe("AutofillOverlayContentService", () => {
autofillOverlayContentService["openAutofillInlineMenu"](); autofillOverlayContentService["openAutofillInlineMenu"]();
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("updateAutofillOverlayMenuPosition", { expect(sendExtensionMessageSpy).toHaveBeenCalledWith("updateAutofillInlineMenuPosition", {
overlayElement: AutofillOverlayElement.Button, overlayElement: AutofillOverlayElement.Button,
}); });
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("updateAutofillOverlayMenuPosition", { expect(sendExtensionMessageSpy).toHaveBeenCalledWith("updateAutofillInlineMenuPosition", {
overlayElement: AutofillOverlayElement.List, overlayElement: AutofillOverlayElement.List,
}); });
}); });
@@ -831,29 +830,30 @@ describe("AutofillOverlayContentService", () => {
autofillOverlayContentService["inlineMenuVisibility"] = autofillOverlayContentService["inlineMenuVisibility"] =
AutofillOverlayVisibility.OnButtonClick; AutofillOverlayVisibility.OnButtonClick;
autofillOverlayContentService["openAutofillInlineMenu"]({ isOpeningFullOverlay: false }); autofillOverlayContentService["openAutofillInlineMenu"]({
isOpeningFullAutofillInlineMenu: false,
});
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("updateAutofillOverlayMenuPosition", { expect(sendExtensionMessageSpy).toHaveBeenCalledWith("updateAutofillInlineMenuPosition", {
overlayElement: AutofillOverlayElement.Button, overlayElement: AutofillOverlayElement.Button,
}); });
expect(sendExtensionMessageSpy).not.toHaveBeenCalledWith( expect(sendExtensionMessageSpy).not.toHaveBeenCalledWith("updateAutofillInlineMenuPosition", {
"updateAutofillOverlayMenuPosition", overlayElement: AutofillOverlayElement.List,
{ });
overlayElement: AutofillOverlayElement.List,
},
);
}); });
it("overrides the onButtonClick visibility setting to open both overlay elements", () => { it("overrides the onButtonClick visibility setting to open both overlay elements", () => {
autofillOverlayContentService["inlineMenuVisibility"] = autofillOverlayContentService["inlineMenuVisibility"] =
AutofillOverlayVisibility.OnButtonClick; AutofillOverlayVisibility.OnButtonClick;
autofillOverlayContentService["openAutofillInlineMenu"]({ isOpeningFullOverlay: true }); autofillOverlayContentService["openAutofillInlineMenu"]({
isOpeningFullAutofillInlineMenu: true,
});
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("updateAutofillOverlayMenuPosition", { expect(sendExtensionMessageSpy).toHaveBeenCalledWith("updateAutofillInlineMenuPosition", {
overlayElement: AutofillOverlayElement.Button, overlayElement: AutofillOverlayElement.Button,
}); });
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("updateAutofillOverlayMenuPosition", { expect(sendExtensionMessageSpy).toHaveBeenCalledWith("updateAutofillInlineMenuPosition", {
overlayElement: AutofillOverlayElement.List, overlayElement: AutofillOverlayElement.List,
}); });
}); });
@@ -962,7 +962,7 @@ describe("AutofillOverlayContentService", () => {
}); });
}); });
describe("redirectOverlayFocusOut", () => { describe("redirectInlineMenuFocusOut", () => {
let autofillFieldElement: ElementWithOpId<FormFieldElement>; let autofillFieldElement: ElementWithOpId<FormFieldElement>;
let autofillFieldFocusSpy: jest.SpyInstance; let autofillFieldFocusSpy: jest.SpyInstance;
let findTabsSpy: jest.SpyInstance; let findTabsSpy: jest.SpyInstance;
@@ -1003,7 +1003,7 @@ describe("AutofillOverlayContentService", () => {
it("skips focusing an element if the overlay is not visible", async () => { it("skips focusing an element if the overlay is not visible", async () => {
isInlineMenuListVisibleSpy.mockResolvedValue(false); isInlineMenuListVisibleSpy.mockResolvedValue(false);
await autofillOverlayContentService.redirectOverlayFocusOut(RedirectFocusDirection.Next); await autofillOverlayContentService.redirectInlineMenuFocusOut(RedirectFocusDirection.Next);
expect(findTabsSpy).not.toHaveBeenCalled(); expect(findTabsSpy).not.toHaveBeenCalled();
}); });
@@ -1011,13 +1011,15 @@ describe("AutofillOverlayContentService", () => {
it("skips focusing an element if no recently focused field exists", async () => { it("skips focusing an element if no recently focused field exists", async () => {
autofillOverlayContentService["mostRecentlyFocusedField"] = undefined; autofillOverlayContentService["mostRecentlyFocusedField"] = undefined;
await autofillOverlayContentService.redirectOverlayFocusOut(RedirectFocusDirection.Next); await autofillOverlayContentService.redirectInlineMenuFocusOut(RedirectFocusDirection.Next);
expect(findTabsSpy).not.toHaveBeenCalled(); expect(findTabsSpy).not.toHaveBeenCalled();
}); });
it("focuses the most recently focused field if the focus direction is `Current`", async () => { it("focuses the most recently focused field if the focus direction is `Current`", async () => {
await autofillOverlayContentService.redirectOverlayFocusOut(RedirectFocusDirection.Current); await autofillOverlayContentService.redirectInlineMenuFocusOut(
RedirectFocusDirection.Current,
);
expect(findTabsSpy).not.toHaveBeenCalled(); expect(findTabsSpy).not.toHaveBeenCalled();
expect(autofillFieldFocusSpy).toHaveBeenCalled(); expect(autofillFieldFocusSpy).toHaveBeenCalled();
@@ -1025,7 +1027,9 @@ describe("AutofillOverlayContentService", () => {
it("removes the overlay if the focus direction is `Current`", async () => { it("removes the overlay if the focus direction is `Current`", async () => {
jest.useFakeTimers(); jest.useFakeTimers();
await autofillOverlayContentService.redirectOverlayFocusOut(RedirectFocusDirection.Current); await autofillOverlayContentService.redirectInlineMenuFocusOut(
RedirectFocusDirection.Current,
);
jest.advanceTimersByTime(150); jest.advanceTimersByTime(150);
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu"); expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu");
@@ -1039,7 +1043,7 @@ describe("AutofillOverlayContentService", () => {
nextFocusableElement, nextFocusableElement,
]); ]);
await autofillOverlayContentService.redirectOverlayFocusOut(RedirectFocusDirection.Next); await autofillOverlayContentService.redirectInlineMenuFocusOut(RedirectFocusDirection.Next);
expect(findTabsSpy).toHaveBeenCalledWith(globalThis.document.body, { getShadowRoot: true }); expect(findTabsSpy).toHaveBeenCalledWith(globalThis.document.body, { getShadowRoot: true });
}); });
@@ -1047,7 +1051,9 @@ describe("AutofillOverlayContentService", () => {
it("focuses the previous focusable element if the focus direction is `Previous`", async () => { it("focuses the previous focusable element if the focus direction is `Previous`", async () => {
jest.spyOn(previousFocusableElement, "focus"); jest.spyOn(previousFocusableElement, "focus");
await autofillOverlayContentService.redirectOverlayFocusOut(RedirectFocusDirection.Previous); await autofillOverlayContentService.redirectInlineMenuFocusOut(
RedirectFocusDirection.Previous,
);
expect(autofillFieldFocusSpy).not.toHaveBeenCalled(); expect(autofillFieldFocusSpy).not.toHaveBeenCalled();
expect(previousFocusableElement.focus).toHaveBeenCalled(); expect(previousFocusableElement.focus).toHaveBeenCalled();
@@ -1056,7 +1062,7 @@ describe("AutofillOverlayContentService", () => {
it("focuses the next focusable element if the focus direction is `Next`", async () => { it("focuses the next focusable element if the focus direction is `Next`", async () => {
jest.spyOn(nextFocusableElement, "focus"); jest.spyOn(nextFocusableElement, "focus");
await autofillOverlayContentService.redirectOverlayFocusOut(RedirectFocusDirection.Next); await autofillOverlayContentService.redirectInlineMenuFocusOut(RedirectFocusDirection.Next);
expect(autofillFieldFocusSpy).not.toHaveBeenCalled(); expect(autofillFieldFocusSpy).not.toHaveBeenCalled();
expect(nextFocusableElement.focus).toHaveBeenCalled(); expect(nextFocusableElement.focus).toHaveBeenCalled();
@@ -1104,8 +1110,8 @@ describe("AutofillOverlayContentService", () => {
globalThis.dispatchEvent(new Event(EVENTS.SCROLL)); globalThis.dispatchEvent(new Event(EVENTS.SCROLL));
await flushPromises(); await flushPromises();
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("updateAutofillOverlayMenuHidden", { expect(sendExtensionMessageSpy).toHaveBeenCalledWith("updateAutofillInlineMenuHidden", {
isOverlayHidden: true, isAutofillInlineMenuHidden: true,
setTransparentOverlay: false, setTransparentOverlay: false,
}); });
}); });
@@ -1132,12 +1138,12 @@ describe("AutofillOverlayContentService", () => {
await flushPromises(); await flushPromises();
jest.advanceTimersByTime(800); jest.advanceTimersByTime(800);
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("updateAutofillOverlayMenuHidden", { expect(sendExtensionMessageSpy).toHaveBeenCalledWith("updateAutofillInlineMenuHidden", {
isOverlayHidden: false, isAutofillInlineMenuHidden: false,
setTransparentOverlay: true, setTransparentOverlay: true,
}); });
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu", { expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu", {
forceCloseOverlay: true, forceCloseAutofillInlineMenu: true,
}); });
}); });
@@ -1163,10 +1169,10 @@ describe("AutofillOverlayContentService", () => {
jest.advanceTimersByTime(800); jest.advanceTimersByTime(800);
await flushPromises(); await flushPromises();
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("updateAutofillOverlayMenuPosition", { expect(sendExtensionMessageSpy).toHaveBeenCalledWith("updateAutofillInlineMenuPosition", {
overlayElement: AutofillOverlayElement.Button, overlayElement: AutofillOverlayElement.Button,
}); });
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("updateAutofillOverlayMenuPosition", { expect(sendExtensionMessageSpy).toHaveBeenCalledWith("updateAutofillInlineMenuPosition", {
overlayElement: AutofillOverlayElement.List, overlayElement: AutofillOverlayElement.List,
}); });
expect(clearUserInteractionEventTimeoutSpy).toHaveBeenCalled(); expect(clearUserInteractionEventTimeoutSpy).toHaveBeenCalled();
@@ -1191,7 +1197,7 @@ describe("AutofillOverlayContentService", () => {
await flushPromises(); await flushPromises();
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu", { expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu", {
forceCloseOverlay: true, forceCloseAutofillInlineMenu: true,
}); });
}); });
}); });
@@ -1201,7 +1207,7 @@ describe("AutofillOverlayContentService", () => {
autofillOverlayContentService["handleVisibilityChangeEvent"](); autofillOverlayContentService["handleVisibilityChangeEvent"]();
expect(sendExtensionMessageSpy).not.toHaveBeenCalledWith("closeAutofillInlineMenu", { expect(sendExtensionMessageSpy).not.toHaveBeenCalledWith("closeAutofillInlineMenu", {
forceCloseOverlay: true, forceCloseAutofillInlineMenu: true,
}); });
}); });
@@ -1215,7 +1221,7 @@ describe("AutofillOverlayContentService", () => {
autofillOverlayContentService["handleVisibilityChangeEvent"](); autofillOverlayContentService["handleVisibilityChangeEvent"]();
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu", { expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu", {
forceCloseOverlay: true, forceCloseAutofillInlineMenu: true,
}); });
}); });
}); });
@@ -1244,7 +1250,7 @@ describe("AutofillOverlayContentService", () => {
}); });
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises // eslint-disable-next-line @typescript-eslint/no-floating-promises
autofillOverlayContentService.setupAutofillOverlayListenerOnField( autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
autofillFieldData, autofillFieldData,
); );

View File

@@ -18,7 +18,7 @@ import { elementIsFillableFormField, getAttributeBoolean, sendExtensionMessage }
import { import {
AutofillOverlayContentExtensionMessageHandlers, AutofillOverlayContentExtensionMessageHandlers,
AutofillOverlayContentService as AutofillOverlayContentServiceInterface, AutofillOverlayContentService as AutofillOverlayContentServiceInterface,
OpenAutofillOverlayOptions, OpenAutofillInlineMenuOptions,
} from "./abstractions/autofill-overlay-content.service"; } from "./abstractions/autofill-overlay-content.service";
import { AutoFillConstants } from "./autofill-constants"; import { AutoFillConstants } from "./autofill-constants";
@@ -46,9 +46,10 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
blurMostRecentOverlayField: () => this.blurMostRecentOverlayField(), blurMostRecentOverlayField: () => this.blurMostRecentOverlayField(),
bgUnlockPopoutOpened: () => this.blurMostRecentOverlayField(true), bgUnlockPopoutOpened: () => this.blurMostRecentOverlayField(true),
bgVaultItemRepromptPopoutOpened: () => this.blurMostRecentOverlayField(true), bgVaultItemRepromptPopoutOpened: () => this.blurMostRecentOverlayField(true),
redirectOverlayFocusOut: ({ message }) => redirectInlineMenuFocusOut: ({ message }) =>
this.redirectOverlayFocusOut(message?.data?.direction), this.redirectInlineMenuFocusOut(message?.data?.direction),
updateInlineMenuVisibility: ({ message }) => this.updateInlineMenuVisibility(message), updateAutofillInlineMenuVisibility: ({ message }) =>
this.updateAutofillInlineMenuVisibility(message),
getSubFrameOffsets: ({ message }) => this.getSubFrameOffsets(message), getSubFrameOffsets: ({ message }) => this.getSubFrameOffsets(message),
getSubFrameOffsetsFromWindowMessage: ({ message }) => getSubFrameOffsetsFromWindowMessage: ({ message }) =>
this.getSubFrameOffsetsFromWindowMessage(message), this.getSubFrameOffsetsFromWindowMessage(message),
@@ -68,13 +69,13 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
} }
/** /**
* Sets up the autofill overlay listener on the form field element. This method is called * Sets up the autofill inline menu listener on the form field element. This method is called
* during the page details collection process. * during the page details collection process.
* *
* @param formFieldElement - Form field elements identified during the page details collection process. * @param formFieldElement - Form field elements identified during the page details collection process.
* @param autofillFieldData - Autofill field data captured from the form field element. * @param autofillFieldData - Autofill field data captured from the form field element.
*/ */
async setupAutofillOverlayListenerOnField( async setupAutofillInlineMenuListenerOnField(
formFieldElement: ElementWithOpId<FormFieldElement>, formFieldElement: ElementWithOpId<FormFieldElement>,
autofillFieldData: AutofillField, autofillFieldData: AutofillField,
) { ) {
@@ -111,8 +112,8 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
* *
* @param options - Options for opening the autofill overlay. * @param options - Options for opening the autofill overlay.
*/ */
openAutofillInlineMenu(options: OpenAutofillOverlayOptions = {}) { openAutofillInlineMenu(options: OpenAutofillInlineMenuOptions = {}) {
const { isFocusingFieldElement, isOpeningFullOverlay, authStatus } = options; const { isFocusingFieldElement, isOpeningFullAutofillInlineMenu, authStatus } = options;
if (!this.mostRecentlyFocusedField) { if (!this.mostRecentlyFocusedField) {
return; return;
} }
@@ -134,13 +135,13 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
if ( if (
this.inlineMenuVisibility === AutofillOverlayVisibility.OnButtonClick && this.inlineMenuVisibility === AutofillOverlayVisibility.OnButtonClick &&
!isOpeningFullOverlay !isOpeningFullAutofillInlineMenu
) { ) {
this.updateOverlayButtonPosition(); this.updateAutofillInlineMenuButtonPosition();
return; return;
} }
this.updateOverlayElementsPosition(); this.updateAutofillInlineMenuElementsPosition();
} }
/** /**
@@ -187,7 +188,7 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
* *
* @param direction - The direction to redirect the focus out. * @param direction - The direction to redirect the focus out.
*/ */
async redirectOverlayFocusOut(direction?: string) { async redirectInlineMenuFocusOut(direction?: string) {
if (!direction || !this.mostRecentlyFocusedField || !(await this.isInlineMenuListVisible())) { if (!direction || !this.mostRecentlyFocusedField || !(await this.isInlineMenuListVisible())) {
return; return;
} }
@@ -290,7 +291,7 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
void this.sendExtensionMessage("updateIsFieldCurrentlyFocused", { void this.sendExtensionMessage("updateIsFieldCurrentlyFocused", {
isFieldCurrentlyFocused: false, isFieldCurrentlyFocused: false,
}); });
void this.sendExtensionMessage("checkAutofillOverlayMenuFocused"); void this.sendExtensionMessage("checkAutofillInlineMenuFocused");
}; };
/** /**
@@ -305,7 +306,7 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
const eventCode = event.code; const eventCode = event.code;
if (eventCode === "Escape") { if (eventCode === "Escape") {
void this.sendExtensionMessage("closeAutofillInlineMenu", { void this.sendExtensionMessage("closeAutofillInlineMenu", {
forceCloseOverlay: true, forceCloseAutofillInlineMenu: true,
}); });
return; return;
} }
@@ -319,7 +320,7 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
void this.focusOverlayMenuList(); void this.focusInlineMenuList();
} }
}; };
@@ -328,15 +329,15 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
* the overlay will be opened and the list will be focused after a short delay. Ensures * the overlay will be opened and the list will be focused after a short delay. Ensures
* that the overlay list is focused when the user presses the down arrow key. * that the overlay list is focused when the user presses the down arrow key.
*/ */
private async focusOverlayMenuList() { private async focusInlineMenuList() {
if (this.mostRecentlyFocusedField && !(await this.isInlineMenuListVisible())) { if (this.mostRecentlyFocusedField && !(await this.isInlineMenuListVisible())) {
await this.updateMostRecentlyFocusedField(this.mostRecentlyFocusedField); await this.updateMostRecentlyFocusedField(this.mostRecentlyFocusedField);
this.openAutofillInlineMenu({ isOpeningFullOverlay: true }); this.openAutofillInlineMenu({ isOpeningFullAutofillInlineMenu: true });
setTimeout(() => this.sendExtensionMessage("focusAutofillOverlayMenuList"), 125); setTimeout(() => this.sendExtensionMessage("focusAutofillInlineMenuList"), 125);
return; return;
} }
void this.sendExtensionMessage("focusAutofillOverlayMenuList"); void this.sendExtensionMessage("focusAutofillInlineMenuList");
} }
/** /**
@@ -365,10 +366,10 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
this.storeModifiedFormElement(formFieldElement); this.storeModifiedFormElement(formFieldElement);
if (await this.hideOverlayListOnFilledField(formFieldElement)) { if (await this.hideAutofillInlineMenuListOnFilledField(formFieldElement)) {
void this.sendExtensionMessage("closeAutofillInlineMenu", { void this.sendExtensionMessage("closeAutofillInlineMenu", {
overlayElement: AutofillOverlayElement.List, overlayElement: AutofillOverlayElement.List,
forceCloseOverlay: true, forceCloseAutofillInlineMenu: true,
}); });
return; return;
} }
@@ -461,12 +462,16 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
) { ) {
await this.sendExtensionMessage("closeAutofillInlineMenu", { await this.sendExtensionMessage("closeAutofillInlineMenu", {
overlayElement: AutofillOverlayElement.List, overlayElement: AutofillOverlayElement.List,
forceCloseOverlay: true, forceCloseAutofillInlineMenu: true,
}); });
} }
if (await this.hideOverlayListOnFilledField(formFieldElement as FillableFormFieldElement)) { if (
this.updateOverlayButtonPosition(); await this.hideAutofillInlineMenuListOnFilledField(
formFieldElement as FillableFormFieldElement,
)
) {
this.updateAutofillInlineMenuButtonPosition();
return; return;
} }
@@ -538,16 +543,16 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
/** /**
* Updates the position of both the overlay button and overlay list. * Updates the position of both the overlay button and overlay list.
*/ */
private updateOverlayElementsPosition() { private updateAutofillInlineMenuElementsPosition() {
this.updateOverlayButtonPosition(); this.updateAutofillInlineMenuButtonPosition();
this.updateOverlayListPosition(); this.updateAutofillInlineMenuListPosition();
} }
/** /**
* Updates the position of the overlay button. * Updates the position of the overlay button.
*/ */
private updateOverlayButtonPosition() { private updateAutofillInlineMenuButtonPosition() {
void this.sendExtensionMessage("updateAutofillOverlayMenuPosition", { void this.sendExtensionMessage("updateAutofillInlineMenuPosition", {
overlayElement: AutofillOverlayElement.Button, overlayElement: AutofillOverlayElement.Button,
}); });
} }
@@ -555,8 +560,8 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
/** /**
* Updates the position of the overlay list. * Updates the position of the overlay list.
*/ */
private updateOverlayListPosition() { private updateAutofillInlineMenuListPosition() {
void this.sendExtensionMessage("updateAutofillOverlayMenuPosition", { void this.sendExtensionMessage("updateAutofillInlineMenuPosition", {
overlayElement: AutofillOverlayElement.List, overlayElement: AutofillOverlayElement.List,
}); });
} }
@@ -567,9 +572,12 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
* @param isHidden - Indicates if the overlay elements should be hidden. * @param isHidden - Indicates if the overlay elements should be hidden.
* @param setTransparentOverlay - Indicates if the overlay is closing. * @param setTransparentOverlay - Indicates if the overlay is closing.
*/ */
private toggleOverlayHidden(isHidden: boolean, setTransparentOverlay: boolean = false) { private toggleAutofillInlineMenuHidden(
void this.sendExtensionMessage("updateAutofillOverlayMenuHidden", { isHidden: boolean,
isOverlayHidden: isHidden, setTransparentOverlay: boolean = false,
) {
void this.sendExtensionMessage("updateAutofillInlineMenuHidden", {
isAutofillInlineMenuHidden: isHidden,
setTransparentOverlay, setTransparentOverlay,
}); });
} }
@@ -711,7 +719,7 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
autofillFieldData.readonly = getAttributeBoolean(formFieldElement, "disabled"); autofillFieldData.readonly = getAttributeBoolean(formFieldElement, "disabled");
autofillFieldData.disabled = getAttributeBoolean(formFieldElement, "disabled"); autofillFieldData.disabled = getAttributeBoolean(formFieldElement, "disabled");
autofillFieldData.viewable = true; autofillFieldData.viewable = true;
void this.setupAutofillOverlayListenerOnField(formFieldElement, autofillFieldData); void this.setupAutofillInlineMenuListenerOnField(formFieldElement, autofillFieldData);
} }
this.removeHiddenFieldFallbackListener(formFieldElement); this.removeHiddenFieldFallbackListener(formFieldElement);
@@ -760,7 +768,7 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
return; return;
} }
this.toggleOverlayHidden(true); this.toggleAutofillInlineMenuHidden(true);
this.clearUserInteractionEventTimeout(); this.clearUserInteractionEventTimeout();
this.userInteractionEventTimeout = setTimeout(this.triggerOverlayRepositionUpdates, 750); this.userInteractionEventTimeout = setTimeout(this.triggerOverlayRepositionUpdates, 750);
}; };
@@ -779,25 +787,25 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
*/ */
private triggerOverlayRepositionUpdates = async () => { private triggerOverlayRepositionUpdates = async () => {
if (!this.recentlyFocusedFieldIsCurrentlyFocused()) { if (!this.recentlyFocusedFieldIsCurrentlyFocused()) {
this.toggleOverlayHidden(false, true); this.toggleAutofillInlineMenuHidden(false, true);
void this.sendExtensionMessage("closeAutofillInlineMenu", { void this.sendExtensionMessage("closeAutofillInlineMenu", {
forceCloseOverlay: true, forceCloseAutofillInlineMenu: true,
}); });
return; return;
} }
await this.updateMostRecentlyFocusedField(this.mostRecentlyFocusedField); await this.updateMostRecentlyFocusedField(this.mostRecentlyFocusedField);
this.updateOverlayElementsPosition(); this.updateAutofillInlineMenuElementsPosition();
setTimeout(async () => { setTimeout(async () => {
this.toggleOverlayHidden(false); this.toggleAutofillInlineMenuHidden(false);
if ( if (
await this.hideOverlayListOnFilledField( await this.hideAutofillInlineMenuListOnFilledField(
this.mostRecentlyFocusedField as FillableFormFieldElement, this.mostRecentlyFocusedField as FillableFormFieldElement,
) )
) { ) {
void this.sendExtensionMessage("closeAutofillInlineMenu", { void this.sendExtensionMessage("closeAutofillInlineMenu", {
overlayElement: AutofillOverlayElement.List, overlayElement: AutofillOverlayElement.List,
forceCloseOverlay: true, forceCloseAutofillInlineMenu: true,
}); });
} }
}, 50); }, 50);
@@ -808,7 +816,7 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
} }
void this.sendExtensionMessage("closeAutofillInlineMenu", { void this.sendExtensionMessage("closeAutofillInlineMenu", {
forceCloseOverlay: true, forceCloseAutofillInlineMenu: true,
}); });
}; };
@@ -837,7 +845,7 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
); );
} }
private async hideOverlayListOnFilledField( private async hideAutofillInlineMenuListOnFilledField(
formFieldElement?: FillableFormFieldElement, formFieldElement?: FillableFormFieldElement,
): Promise<boolean> { ): Promise<boolean> {
return ( return (
@@ -869,7 +877,7 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
this.mostRecentlyFocusedField = null; this.mostRecentlyFocusedField = null;
void this.sendExtensionMessage("closeAutofillInlineMenu", { void this.sendExtensionMessage("closeAutofillInlineMenu", {
forceCloseOverlay: true, forceCloseAutofillInlineMenu: true,
}); });
}; };
@@ -981,7 +989,7 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
}); });
}; };
private updateInlineMenuVisibility({ data }: AutofillExtensionMessage) { private updateAutofillInlineMenuVisibility({ data }: AutofillExtensionMessage) {
if (isNaN(data?.inlineMenuVisibility)) { if (isNaN(data?.inlineMenuVisibility)) {
return; return;
} }

View File

@@ -2105,7 +2105,7 @@ export default class AutofillService implements AutofillServiceInterface {
if (!inlineMenuPreviouslyDisabled && !inlineMenuCurrentlyDisabled) { if (!inlineMenuPreviouslyDisabled && !inlineMenuCurrentlyDisabled) {
const tabs = await BrowserApi.tabsQuery({}); const tabs = await BrowserApi.tabsQuery({});
tabs.forEach((tab) => tabs.forEach((tab) =>
BrowserApi.tabSendMessageData(tab, "updateInlineMenuVisibility", { BrowserApi.tabSendMessageData(tab, "updateAutofillInlineMenuVisibility", {
inlineMenuVisibility: currentSetting, inlineMenuVisibility: currentSetting,
}), }),
); );

View File

@@ -2578,7 +2578,7 @@ describe("CollectAutofillContentService", () => {
); );
setupAutofillOverlayListenerOnFieldSpy = jest.spyOn( setupAutofillOverlayListenerOnFieldSpy = jest.spyOn(
collectAutofillContentService["autofillOverlayContentService"], collectAutofillContentService["autofillOverlayContentService"],
"setupAutofillOverlayListenerOnField", "setupAutofillInlineMenuListenerOnField",
); );
}); });

View File

@@ -205,7 +205,7 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
autofillField.viewable = await this.domElementVisibilityService.isFormFieldViewable(element); autofillField.viewable = await this.domElementVisibilityService.isFormFieldViewable(element);
if (!currentViewableState && autofillField.viewable) { if (!currentViewableState && autofillField.viewable) {
await this.autofillOverlayContentService?.setupAutofillOverlayListenerOnField( await this.autofillOverlayContentService?.setupAutofillInlineMenuListenerOnField(
element, element,
autofillField, autofillField,
); );
@@ -381,7 +381,7 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
if (elementIsSpanElement(element)) { if (elementIsSpanElement(element)) {
this.cacheAutofillFieldElement(index, element, autofillFieldBase); this.cacheAutofillFieldElement(index, element, autofillFieldBase);
void this.autofillOverlayContentService?.setupAutofillOverlayListenerOnField( void this.autofillOverlayContentService?.setupAutofillInlineMenuListenerOnField(
element, element,
autofillFieldBase, autofillFieldBase,
); );
@@ -424,7 +424,7 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
}; };
this.cacheAutofillFieldElement(index, element, autofillField); this.cacheAutofillFieldElement(index, element, autofillField);
void this.autofillOverlayContentService?.setupAutofillOverlayListenerOnField( void this.autofillOverlayContentService?.setupAutofillInlineMenuListenerOnField(
element, element,
autofillField, autofillField,
); );
@@ -1321,7 +1321,7 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
const cachedAutofillFieldElement = this.autofillFieldElements.get(formFieldElement); const cachedAutofillFieldElement = this.autofillFieldElements.get(formFieldElement);
cachedAutofillFieldElement.viewable = true; cachedAutofillFieldElement.viewable = true;
void this.autofillOverlayContentService?.setupAutofillOverlayListenerOnField( void this.autofillOverlayContentService?.setupAutofillInlineMenuListenerOnField(
formFieldElement, formFieldElement,
cachedAutofillFieldElement, cachedAutofillFieldElement,
); );

View File

@@ -38,7 +38,7 @@ describe("generateRandomCustomElementName", () => {
describe("sendExtensionMessage", () => { describe("sendExtensionMessage", () => {
it("sends a message to the extention", () => { it("sends a message to the extention", () => {
const extensionMessageResponse = sendExtensionMessage("updateAutofillOverlayMenuHidden", { const extensionMessageResponse = sendExtensionMessage("updateAutofillInlineMenuHidden", {
display: "none", display: "none",
}); });
jest.spyOn(chrome.runtime, "sendMessage"); jest.spyOn(chrome.runtime, "sendMessage");