mirror of
https://github.com/bitwarden/browser
synced 2025-12-20 18:23:31 +00:00
[PM-5189] Implementing a methodology for triggering subframe updates from layout-shift
This commit is contained in:
@@ -65,6 +65,7 @@ export type OverlayBackgroundExtensionMessage = {
|
|||||||
subFrameData?: SubFrameOffsetData;
|
subFrameData?: SubFrameOffsetData;
|
||||||
focusedFieldData?: FocusedFieldData;
|
focusedFieldData?: FocusedFieldData;
|
||||||
styles?: Partial<CSSStyleDeclaration>;
|
styles?: Partial<CSSStyleDeclaration>;
|
||||||
|
triggerInlineMenuPositionUpdate?: boolean;
|
||||||
data?: LockedVaultPendingNotificationsData;
|
data?: LockedVaultPendingNotificationsData;
|
||||||
} & OverlayAddNewItemMessage &
|
} & OverlayAddNewItemMessage &
|
||||||
CloseInlineMenuMessage;
|
CloseInlineMenuMessage;
|
||||||
@@ -120,7 +121,7 @@ export type OverlayBackgroundExtensionMessageHandlers = {
|
|||||||
checkShouldRepositionInlineMenu: ({ sender }: BackgroundSenderParam) => boolean;
|
checkShouldRepositionInlineMenu: ({ sender }: BackgroundSenderParam) => boolean;
|
||||||
getCurrentTabFrameId: ({ sender }: BackgroundSenderParam) => number;
|
getCurrentTabFrameId: ({ sender }: BackgroundSenderParam) => number;
|
||||||
updateSubFrameData: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
updateSubFrameData: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
||||||
rebuildSubFrameOffsets: ({ sender }: BackgroundSenderParam) => void;
|
rebuildSubFrameOffsets: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
||||||
destroyAutofillInlineMenuListeners: ({
|
destroyAutofillInlineMenuListeners: ({
|
||||||
message,
|
message,
|
||||||
sender,
|
sender,
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
checkShouldRepositionInlineMenu: ({ sender }) => this.checkShouldRepositionInlineMenu(sender),
|
checkShouldRepositionInlineMenu: ({ sender }) => this.checkShouldRepositionInlineMenu(sender),
|
||||||
getCurrentTabFrameId: ({ sender }) => this.getSenderFrameId(sender),
|
getCurrentTabFrameId: ({ sender }) => this.getSenderFrameId(sender),
|
||||||
updateSubFrameData: ({ message, sender }) => this.updateSubFrameData(message, sender),
|
updateSubFrameData: ({ message, sender }) => this.updateSubFrameData(message, sender),
|
||||||
rebuildSubFrameOffsets: ({ sender }) => this.rebuildSubFrameOffsets(sender),
|
rebuildSubFrameOffsets: ({ message, sender }) => this.rebuildSubFrameOffsets(message, sender),
|
||||||
destroyAutofillInlineMenuListeners: ({ message, sender }) =>
|
destroyAutofillInlineMenuListeners: ({ message, sender }) =>
|
||||||
this.triggerDestroyInlineMenuListeners(sender.tab, message.subFrameData.frameId),
|
this.triggerDestroyInlineMenuListeners(sender.tab, message.subFrameData.frameId),
|
||||||
collectPageDetailsResponse: ({ message, sender }) => this.storePageDetails(message, sender),
|
collectPageDetailsResponse: ({ message, sender }) => this.storePageDetails(message, sender),
|
||||||
@@ -382,9 +382,13 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
* the field currently focused. We trigger a re-calculation of the field's position
|
* the field currently focused. We trigger a re-calculation of the field's position
|
||||||
* and as a result, the sub frame offsets of that frame will be updated.
|
* and as a result, the sub frame offsets of that frame will be updated.
|
||||||
*
|
*
|
||||||
|
* @param message - The message received from the `rebuildSubFrameOffsets` command
|
||||||
* @param sender - The sender of the message
|
* @param sender - The sender of the message
|
||||||
*/
|
*/
|
||||||
private async rebuildSubFrameOffsets(sender: chrome.runtime.MessageSender) {
|
private async rebuildSubFrameOffsets(
|
||||||
|
message: OverlayBackgroundExtensionMessage,
|
||||||
|
sender: chrome.runtime.MessageSender,
|
||||||
|
) {
|
||||||
if (sender.frameId === this.focusedFieldData?.frameId) {
|
if (sender.frameId === this.focusedFieldData?.frameId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -406,10 +410,12 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateInlineMenuPositionTimeout = globalThis.setTimeout(
|
if (message.triggerInlineMenuPositionUpdate) {
|
||||||
() => this.updateInlineMenuPositionAfterSubFrameRebuild(sender),
|
this.updateInlineMenuPositionTimeout = globalThis.setTimeout(
|
||||||
650,
|
() => this.updateInlineMenuPositionAfterSubFrameRebuild(sender),
|
||||||
);
|
650,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
|||||||
private focusedFieldData: FocusedFieldData;
|
private focusedFieldData: FocusedFieldData;
|
||||||
private userInteractionEventTimeout: number | NodeJS.Timeout;
|
private userInteractionEventTimeout: number | NodeJS.Timeout;
|
||||||
private recalculateSubFrameOffsetsTimeout: number | NodeJS.Timeout;
|
private recalculateSubFrameOffsetsTimeout: number | NodeJS.Timeout;
|
||||||
|
private performanceObserver: PerformanceObserver;
|
||||||
private autofillFieldKeywordsMap: WeakMap<AutofillField, string> = new WeakMap();
|
private autofillFieldKeywordsMap: WeakMap<AutofillField, string> = new WeakMap();
|
||||||
private eventHandlersMemo: { [key: string]: EventListener } = {};
|
private eventHandlersMemo: { [key: string]: EventListener } = {};
|
||||||
private readonly extensionMessageHandlers: AutofillOverlayContentExtensionMessageHandlers = {
|
private readonly extensionMessageHandlers: AutofillOverlayContentExtensionMessageHandlers = {
|
||||||
@@ -786,6 +787,8 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
|||||||
capture: true,
|
capture: true,
|
||||||
});
|
});
|
||||||
globalThis.addEventListener(EVENTS.RESIZE, this.handleOverlayRepositionEvent);
|
globalThis.addEventListener(EVENTS.RESIZE, this.handleOverlayRepositionEvent);
|
||||||
|
this.performanceObserver = new PerformanceObserver(() => this.rebuildSubFrameOffsets(0, false));
|
||||||
|
this.performanceObserver.observe({ type: "layout-shift", buffered: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -820,11 +823,14 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
|||||||
/**
|
/**
|
||||||
* Triggers a rebuild of a sub frame's offsets within the tab.
|
* Triggers a rebuild of a sub frame's offsets within the tab.
|
||||||
*/
|
*/
|
||||||
private rebuildSubFrameOffsets() {
|
private rebuildSubFrameOffsets(delay: number = 150, triggerInlineMenuPositionUpdate = true) {
|
||||||
this.clearRecalculateSubFrameOffsetsTimeout();
|
this.clearRecalculateSubFrameOffsetsTimeout();
|
||||||
this.recalculateSubFrameOffsetsTimeout = globalThis.setTimeout(
|
this.recalculateSubFrameOffsetsTimeout = globalThis.setTimeout(
|
||||||
() => void this.sendExtensionMessage("rebuildSubFrameOffsets"),
|
() =>
|
||||||
150,
|
void this.sendExtensionMessage("rebuildSubFrameOffsets", {
|
||||||
|
triggerInlineMenuPositionUpdate,
|
||||||
|
}),
|
||||||
|
delay,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1161,6 +1167,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
|||||||
this.handleVisibilityChangeEvent,
|
this.handleVisibilityChangeEvent,
|
||||||
);
|
);
|
||||||
globalThis.removeEventListener(EVENTS.FOCUSOUT, this.handleFormFieldBlurEvent);
|
globalThis.removeEventListener(EVENTS.FOCUSOUT, this.handleFormFieldBlurEvent);
|
||||||
|
this.performanceObserver?.disconnect();
|
||||||
this.removeOverlayRepositionEventListeners();
|
this.removeOverlayRepositionEventListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user