[PM-5189] Working through content script port improvement

This commit is contained in:
Cesar Gonzalez 2024-06-19 02:30:34 -05:00
parent e30a1ebc5d
commit 8a48e576e1
No known key found for this signature in database
GPG Key ID: 3381A5457F8CCECF
6 changed files with 32 additions and 54 deletions

View File

@ -94,15 +94,10 @@ export type BackgroundOnMessageHandlerParams = BackgroundMessageParam & Backgrou
export type OverlayBackgroundExtensionMessageHandlers = { export type OverlayBackgroundExtensionMessageHandlers = {
[key: string]: CallableFunction; [key: string]: CallableFunction;
triggerAutofillOverlayReposition: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
checkIsInlineMenuCiphersPopulated: ({ sender }: BackgroundSenderParam) => void; checkIsInlineMenuCiphersPopulated: ({ sender }: BackgroundSenderParam) => void;
updateFocusedFieldData: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
updateIsFieldCurrentlyFocused: ({ message }: BackgroundMessageParam) => void;
checkIsFieldCurrentlyFocused: () => boolean;
updateIsFieldCurrentlyFilling: ({ message }: BackgroundMessageParam) => void; updateIsFieldCurrentlyFilling: ({ message }: BackgroundMessageParam) => void;
checkIsFieldCurrentlyFilling: () => boolean; checkIsFieldCurrentlyFilling: () => boolean;
getAutofillInlineMenuVisibility: () => void; getAutofillInlineMenuVisibility: () => void;
openAutofillInlineMenu: () => void;
closeAutofillInlineMenu: ({ message, sender }: BackgroundOnMessageHandlerParams) => void; closeAutofillInlineMenu: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
checkAutofillInlineMenuFocused: () => void; checkAutofillInlineMenuFocused: () => void;
focusAutofillInlineMenuList: () => void; focusAutofillInlineMenuList: () => void;
@ -132,7 +127,6 @@ export type OverlayPortMessage = OverlayBackgroundExtensionMessage & {
direction?: string; direction?: string;
inlineMenuCipherId?: string; inlineMenuCipherId?: string;
}; };
export type PortMessageParam = { export type PortMessageParam = {
message: OverlayPortMessage; message: OverlayPortMessage;
}; };
@ -145,6 +139,10 @@ export type OverlayContentScriptPortMessageHandlers = {
[key: string]: CallableFunction; [key: string]: CallableFunction;
autofillOverlayElementClosed: ({ message, port }: PortOnMessageHandlerParams) => void; autofillOverlayElementClosed: ({ message, port }: PortOnMessageHandlerParams) => void;
autofillOverlayAddNewVaultItem: ({ message, port }: PortOnMessageHandlerParams) => void; autofillOverlayAddNewVaultItem: ({ message, port }: PortOnMessageHandlerParams) => void;
triggerAutofillOverlayReposition: ({ port }: PortConnectionParam) => void;
updateFocusedFieldData: ({ message, port }: PortOnMessageHandlerParams) => void;
updateIsFieldCurrentlyFocused: ({ message }: PortMessageParam) => void;
openAutofillInlineMenu: () => void;
}; };
export type InlineMenuButtonPortMessageHandlers = { export type InlineMenuButtonPortMessageHandlers = {

View File

@ -790,24 +790,6 @@ describe("OverlayBackground", () => {
}); });
}); });
describe("checkIsFieldCurrentlyFocused message handler", () => {
it("returns true when a form field is currently focused", async () => {
sendMockExtensionMessage({
command: "updateIsFieldCurrentlyFocused",
isFieldCurrentlyFocused: true,
});
sendMockExtensionMessage(
{ command: "checkIsFieldCurrentlyFocused" },
mock<chrome.runtime.MessageSender>(),
sendResponse,
);
await flushPromises();
expect(sendResponse).toHaveBeenCalledWith(true);
});
});
describe("checkIsFieldCurrentlyFilling message handler", () => { describe("checkIsFieldCurrentlyFilling message handler", () => {
it("returns true if autofill is currently running", async () => { it("returns true if autofill is currently running", async () => {
sendMockExtensionMessage({ sendMockExtensionMessage({

View File

@ -76,16 +76,11 @@ export class OverlayBackground implements OverlayBackgroundInterface {
private isFieldCurrentlyFilling: boolean = false; private isFieldCurrentlyFilling: boolean = false;
private iconsServerUrl: string; private iconsServerUrl: string;
private readonly extensionMessageHandlers: OverlayBackgroundExtensionMessageHandlers = { private readonly extensionMessageHandlers: OverlayBackgroundExtensionMessageHandlers = {
triggerAutofillOverlayReposition: ({ sender }) => this.triggerOverlayReposition(sender),
checkIsInlineMenuCiphersPopulated: ({ sender }) => checkIsInlineMenuCiphersPopulated: ({ sender }) =>
this.checkIsInlineMenuCiphersPopulated(sender), this.checkIsInlineMenuCiphersPopulated(sender),
updateFocusedFieldData: ({ message, sender }) => this.setFocusedFieldData(message, sender),
updateIsFieldCurrentlyFocused: ({ message }) => this.updateIsFieldCurrentlyFocused(message),
checkIsFieldCurrentlyFocused: () => this.checkIsFieldCurrentlyFocused(),
updateIsFieldCurrentlyFilling: ({ message }) => this.updateIsFieldCurrentlyFilling(message), updateIsFieldCurrentlyFilling: ({ message }) => this.updateIsFieldCurrentlyFilling(message),
checkIsFieldCurrentlyFilling: () => this.checkIsFieldCurrentlyFilling(), checkIsFieldCurrentlyFilling: () => this.checkIsFieldCurrentlyFilling(),
getAutofillInlineMenuVisibility: () => this.getInlineMenuVisibility(), getAutofillInlineMenuVisibility: () => this.getInlineMenuVisibility(),
openAutofillInlineMenu: () => this.openInlineMenu(false),
closeAutofillInlineMenu: ({ message, sender }) => this.closeInlineMenu(sender, message), closeAutofillInlineMenu: ({ message, sender }) => this.closeInlineMenu(sender, message),
checkAutofillInlineMenuFocused: () => this.checkInlineMenuFocused(), checkAutofillInlineMenuFocused: () => this.checkInlineMenuFocused(),
focusAutofillInlineMenuList: () => this.focusInlineMenuList(), focusAutofillInlineMenuList: () => this.focusInlineMenuList(),
@ -111,6 +106,10 @@ export class OverlayBackground implements OverlayBackgroundInterface {
private readonly contentScriptPortMessageHandlers: OverlayContentScriptPortMessageHandlers = { private readonly contentScriptPortMessageHandlers: OverlayContentScriptPortMessageHandlers = {
autofillOverlayElementClosed: ({ message, port }) => this.overlayElementClosed(message, port), autofillOverlayElementClosed: ({ message, port }) => this.overlayElementClosed(message, port),
autofillOverlayAddNewVaultItem: ({ message, port }) => this.addNewVaultItem(message, port), autofillOverlayAddNewVaultItem: ({ message, port }) => this.addNewVaultItem(message, port),
triggerAutofillOverlayReposition: ({ port }) => this.triggerOverlayReposition(port),
updateFocusedFieldData: ({ message, port }) => this.setFocusedFieldData(message, port),
updateIsFieldCurrentlyFocused: ({ message }) => this.updateIsFieldCurrentlyFocused(message),
openAutofillInlineMenu: () => this.openInlineMenu(false),
}; };
private readonly inlineMenuButtonPortMessageHandlers: InlineMenuButtonPortMessageHandlers = { private readonly inlineMenuButtonPortMessageHandlers: InlineMenuButtonPortMessageHandlers = {
triggerDelayedAutofillInlineMenuClosure: ({ port }) => this.triggerDelayedInlineMenuClosure(), triggerDelayedAutofillInlineMenuClosure: ({ port }) => this.triggerDelayedInlineMenuClosure(),
@ -614,13 +613,13 @@ export class OverlayBackground implements OverlayBackgroundInterface {
* the list and button ports and sets them to null. * the list and button ports and sets them to null.
* *
* @param overlayElement - The overlay element that was closed, either the list or button * @param overlayElement - The overlay element that was closed, either the list or button
* @param port - The port that sent the message * @param sender - The sender of the port message
*/ */
private overlayElementClosed( private overlayElementClosed(
{ overlayElement }: OverlayBackgroundExtensionMessage, { overlayElement }: OverlayBackgroundExtensionMessage,
port: chrome.runtime.Port, { sender }: chrome.runtime.Port,
) { ) {
if (port.sender.tab.id !== this.focusedFieldData?.tabId) { if (sender.tab.id !== this.focusedFieldData?.tabId) {
this.expiredPorts.forEach((port) => port.disconnect()); this.expiredPorts.forEach((port) => port.disconnect());
this.expiredPorts = []; this.expiredPorts = [];
return; return;
@ -762,11 +761,11 @@ export class OverlayBackground implements OverlayBackgroundInterface {
* Sets the focused field data to the data passed in the extension message. * Sets the focused field data to the data passed in the extension message.
* *
* @param focusedFieldData - Contains the rects and styles of the focused field. * @param focusedFieldData - Contains the rects and styles of the focused field.
* @param sender - The sender of the extension message * @param sender - The sender of the port message
*/ */
private setFocusedFieldData( private setFocusedFieldData(
{ focusedFieldData }: OverlayBackgroundExtensionMessage, { focusedFieldData }: OverlayBackgroundExtensionMessage,
sender: chrome.runtime.MessageSender, { sender }: chrome.runtime.Port,
) { ) {
if (this.focusedFieldData?.frameId && this.focusedFieldData.frameId !== sender.frameId) { if (this.focusedFieldData?.frameId && this.focusedFieldData.frameId !== sender.frameId) {
void BrowserApi.tabSendMessage( void BrowserApi.tabSendMessage(
@ -1015,9 +1014,12 @@ export class OverlayBackground implements OverlayBackgroundInterface {
* data captured in the extension message. * data captured in the extension message.
* *
* @param login - The login data captured from the extension message * @param login - The login data captured from the extension message
* @param port - The content script port * @param sender - The sender of the port message
*/ */
private async addNewVaultItem({ login }: OverlayAddNewItemMessage, port: chrome.runtime.Port) { private async addNewVaultItem(
{ login }: OverlayAddNewItemMessage,
{ sender }: chrome.runtime.Port,
) {
if (!login) { if (!login) {
return; return;
} }
@ -1041,7 +1043,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
collectionIds: cipherView.collectionIds, collectionIds: cipherView.collectionIds,
}); });
await this.openAddEditVaultItemPopout(port.sender.tab, { cipherId: cipherView.id }); await this.openAddEditVaultItemPopout(sender.tab, { cipherId: cipherView.id });
await BrowserApi.sendMessage("inlineAutofillMenuRefreshAddEditCipher"); await BrowserApi.sendMessage("inlineAutofillMenuRefreshAddEditCipher");
} }
@ -1054,13 +1056,6 @@ export class OverlayBackground implements OverlayBackgroundInterface {
this.isFieldCurrentlyFocused = message.isFieldCurrentlyFocused; this.isFieldCurrentlyFocused = message.isFieldCurrentlyFocused;
} }
/**
* Allows a content script to check if a form field setup for the inline menu is currently focused.
*/
private checkIsFieldCurrentlyFocused() {
return this.isFieldCurrentlyFocused;
}
/** /**
* Updates the property that identifies if a form field is currently being autofilled. * Updates the property that identifies if a form field is currently being autofilled.
* *
@ -1361,7 +1356,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
} }
}; };
private async triggerOverlayReposition(sender: chrome.runtime.MessageSender) { private async triggerOverlayReposition({ sender }: chrome.runtime.Port) {
if (await this.checkShouldRepositionInlineMenu(sender)) { if (await this.checkShouldRepositionInlineMenu(sender)) {
await this.toggleInlineMenuHidden({ isInlineMenuHidden: true }, sender); await this.toggleInlineMenuHidden({ isInlineMenuHidden: true }, sender);
this.calculateInlineMenuPositionSubject.next(sender); this.calculateInlineMenuPositionSubject.next(sender);

View File

@ -425,7 +425,7 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte
*/ */
private sendPortMessage( private sendPortMessage(
command: string, command: string,
message: Omit<AutofillOverlayContentExtensionMessage, "command">, message: Omit<AutofillOverlayContentExtensionMessage, "command"> = {},
) { ) {
this.port.postMessage({ command, ...message }); this.port.postMessage({ command, ...message });
} }

View File

@ -1,6 +1,7 @@
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status"; import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
import { import {
FocusedFieldData,
OverlayAddNewItemMessage, OverlayAddNewItemMessage,
SubFrameOffsetData, SubFrameOffsetData,
} from "../../background/abstractions/overlay.background"; } from "../../background/abstractions/overlay.background";
@ -41,6 +42,8 @@ export type AutofillOverlayContentExtensionMessageHandlers = {
export type AutofillOverlayContentExtensionMessage = { export type AutofillOverlayContentExtensionMessage = {
command: string; command: string;
overlayElement?: AutofillOverlayElementType; overlayElement?: AutofillOverlayElementType;
focusedFieldData?: FocusedFieldData;
isFieldCurrentlyFocused?: boolean;
} & OverlayAddNewItemMessage; } & OverlayAddNewItemMessage;
export interface AutofillOverlayContentService { export interface AutofillOverlayContentService {

View File

@ -347,7 +347,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
* is currently focused. * is currently focused.
*/ */
private handleFormFieldBlurEvent = () => { private handleFormFieldBlurEvent = () => {
void this.sendExtensionMessage("updateIsFieldCurrentlyFocused", { this.sendPortMessage("updateIsFieldCurrentlyFocused", {
isFieldCurrentlyFocused: false, isFieldCurrentlyFocused: false,
}); });
void this.sendExtensionMessage("checkAutofillInlineMenuFocused"); void this.sendExtensionMessage("checkAutofillInlineMenuFocused");
@ -371,7 +371,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
} }
if (eventCode === "Enter" && !(await this.isFieldCurrentlyFilling())) { if (eventCode === "Enter" && !(await this.isFieldCurrentlyFilling())) {
void this.handleOverlayRepositionEvent(); this.handleOverlayRepositionEvent();
return; return;
} }
@ -511,7 +511,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
return; return;
} }
await this.sendExtensionMessage("updateIsFieldCurrentlyFocused", { this.sendPortMessage("updateIsFieldCurrentlyFocused", {
isFieldCurrentlyFocused: true, isFieldCurrentlyFocused: true,
}); });
if (this.userInteractionEventTimeout) { if (this.userInteractionEventTimeout) {
@ -540,7 +540,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
return; return;
} }
void this.sendExtensionMessage("openAutofillInlineMenu"); this.sendPortMessage("openAutofillInlineMenu");
} }
/** /**
@ -621,7 +621,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
focusedFieldRects: { width, height, top, left }, focusedFieldRects: { width, height, top, left },
}; };
await this.sendExtensionMessage("updateFocusedFieldData", { this.sendPortMessage("updateFocusedFieldData", {
focusedFieldData: this.focusedFieldData, focusedFieldData: this.focusedFieldData,
}); });
} }
@ -1071,8 +1071,8 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
* Handles the resize or scroll events that enact * Handles the resize or scroll events that enact
* repositioning of existing overlay elements. * repositioning of existing overlay elements.
*/ */
private handleOverlayRepositionEvent = async () => { private handleOverlayRepositionEvent = () => {
await this.sendExtensionMessage("triggerAutofillOverlayReposition"); this.sendPortMessage("triggerAutofillOverlayReposition");
}; };
private setupRebuildSubFrameOffsetsListeners = () => { private setupRebuildSubFrameOffsetsListeners = () => {
@ -1130,7 +1130,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
*/ */
private sendPortMessage( private sendPortMessage(
command: string, command: string,
message: Omit<AutofillOverlayContentExtensionMessage, "command">, message: Omit<AutofillOverlayContentExtensionMessage, "command"> = {},
) { ) {
this.port.postMessage({ command, ...message }); this.port.postMessage({ command, ...message });
} }