mirror of
https://github.com/bitwarden/browser
synced 2025-12-15 15:53:27 +00:00
[PM-5189] Implementing a methodology for triggering subframe updates from layout-shift
This commit is contained in:
@@ -253,6 +253,9 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
|
|
||||||
if (pageDetails.frameId !== 0 && pageDetails.details.fields.length) {
|
if (pageDetails.frameId !== 0 && pageDetails.details.fields.length) {
|
||||||
void this.buildSubFrameOffsets(pageDetails.tab, pageDetails.frameId, pageDetails.details.url);
|
void this.buildSubFrameOffsets(pageDetails.tab, pageDetails.frameId, pageDetails.details.url);
|
||||||
|
void BrowserApi.tabSendMessage(pageDetails.tab, {
|
||||||
|
command: "setupAutofillInlineMenuReflowObserver",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const pageDetailsMap = this.pageDetailsForTab[sender.tab.id];
|
const pageDetailsMap = this.pageDetailsForTab[sender.tab.id];
|
||||||
@@ -780,6 +783,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
* @param isOpeningFullInlineMenu - Identifies whether the full inline menu should be forced open regardless of other states
|
* @param isOpeningFullInlineMenu - Identifies whether the full inline menu should be forced open regardless of other states
|
||||||
*/
|
*/
|
||||||
private async openInlineMenu(isFocusingFieldElement = false, isOpeningFullInlineMenu = false) {
|
private async openInlineMenu(isFocusingFieldElement = false, isOpeningFullInlineMenu = false) {
|
||||||
|
this.clearDelayedInlineMenuClosure();
|
||||||
const currentTab = await BrowserApi.getTabFromCurrentWindowId();
|
const currentTab = await BrowserApi.getTabFromCurrentWindowId();
|
||||||
|
|
||||||
await BrowserApi.tabSendMessage(
|
await BrowserApi.tabSendMessage(
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ export type AutofillOverlayContentExtensionMessageHandlers = {
|
|||||||
getSubFrameOffsets: ({ message }: AutofillExtensionMessageParam) => Promise<SubFrameOffsetData>;
|
getSubFrameOffsets: ({ message }: AutofillExtensionMessageParam) => Promise<SubFrameOffsetData>;
|
||||||
getSubFrameOffsetsFromWindowMessage: ({ message }: AutofillExtensionMessageParam) => void;
|
getSubFrameOffsetsFromWindowMessage: ({ message }: AutofillExtensionMessageParam) => void;
|
||||||
checkMostRecentlyFocusedFieldHasValue: () => boolean;
|
checkMostRecentlyFocusedFieldHasValue: () => boolean;
|
||||||
|
setupAutofillInlineMenuReflowObserver: () => void;
|
||||||
destroyAutofillInlineMenuListeners: () => void;
|
destroyAutofillInlineMenuListeners: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
|||||||
getSubFrameOffsetsFromWindowMessage: ({ message }) =>
|
getSubFrameOffsetsFromWindowMessage: ({ message }) =>
|
||||||
this.getSubFrameOffsetsFromWindowMessage(message),
|
this.getSubFrameOffsetsFromWindowMessage(message),
|
||||||
checkMostRecentlyFocusedFieldHasValue: () => this.mostRecentlyFocusedFieldHasValue(),
|
checkMostRecentlyFocusedFieldHasValue: () => this.mostRecentlyFocusedFieldHasValue(),
|
||||||
|
setupAutofillInlineMenuReflowObserver: () => this.setupPageReflowEventListeners(),
|
||||||
destroyAutofillInlineMenuListeners: () => this.destroy(),
|
destroyAutofillInlineMenuListeners: () => this.destroy(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -480,7 +481,13 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
|||||||
await this.sendExtensionMessage("updateIsFieldCurrentlyFocused", {
|
await this.sendExtensionMessage("updateIsFieldCurrentlyFocused", {
|
||||||
isFieldCurrentlyFocused: true,
|
isFieldCurrentlyFocused: true,
|
||||||
});
|
});
|
||||||
this.clearUserInteractionEventTimeout();
|
if (this.userInteractionEventTimeout) {
|
||||||
|
this.clearUserInteractionEventTimeout();
|
||||||
|
void this.toggleInlineMenuHidden(false, true);
|
||||||
|
void this.sendExtensionMessage("closeAutofillInlineMenu", {
|
||||||
|
forceCloseInlineMenu: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
const initiallyFocusedField = this.mostRecentlyFocusedField;
|
const initiallyFocusedField = this.mostRecentlyFocusedField;
|
||||||
await this.updateMostRecentlyFocusedField(formFieldElement);
|
await this.updateMostRecentlyFocusedField(formFieldElement);
|
||||||
|
|
||||||
@@ -785,6 +792,10 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
|||||||
}
|
}
|
||||||
|
|
||||||
private setupPageReflowEventListeners() {
|
private setupPageReflowEventListeners() {
|
||||||
|
if (this.reflowPerformanceObserver || this.reflowMutationObserver) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ("PerformanceObserver" in window && "LayoutShift" in window) {
|
if ("PerformanceObserver" in window && "LayoutShift" in window) {
|
||||||
this.reflowPerformanceObserver = new PerformanceObserver(
|
this.reflowPerformanceObserver = new PerformanceObserver(
|
||||||
throttle(this.updateSubFrameOffsetsFromLayoutShiftEvent.bind(this), 10),
|
throttle(this.updateSubFrameOffsetsFromLayoutShiftEvent.bind(this), 10),
|
||||||
@@ -795,7 +806,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.reflowMutationObserver = new MutationObserver(
|
this.reflowMutationObserver = new MutationObserver(
|
||||||
throttle(this.updateSubFrameOffsetsFromDomMutationEvent.bind(this), 10),
|
throttle(this.updateSubFrameForReflow.bind(this), 10),
|
||||||
);
|
);
|
||||||
this.reflowMutationObserver.observe(globalThis.document.documentElement, {
|
this.reflowMutationObserver.observe(globalThis.document.documentElement, {
|
||||||
childList: true,
|
childList: true,
|
||||||
@@ -809,17 +820,20 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
|||||||
for (let index = 0; index < entries.length; index++) {
|
for (let index = 0; index < entries.length; index++) {
|
||||||
const entry = entries[index];
|
const entry = entries[index];
|
||||||
if (entry.sources?.length) {
|
if (entry.sources?.length) {
|
||||||
this.clearUserInteractionEventTimeout();
|
this.updateSubFrameForReflow();
|
||||||
this.clearRecalculateSubFrameOffsetsTimeout();
|
|
||||||
void this.sendExtensionMessage("updateSubFrameOffsetsForReflowEvent");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private updateSubFrameOffsetsFromDomMutationEvent = async () => {
|
private updateSubFrameForReflow = () => {
|
||||||
this.clearUserInteractionEventTimeout();
|
if (this.userInteractionEventTimeout) {
|
||||||
this.clearRecalculateSubFrameOffsetsTimeout();
|
this.clearUserInteractionEventTimeout();
|
||||||
|
void this.toggleInlineMenuHidden(false, true);
|
||||||
|
void this.sendExtensionMessage("closeAutofillInlineMenu", {
|
||||||
|
forceCloseInlineMenu: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
void this.sendExtensionMessage("updateSubFrameOffsetsForReflowEvent");
|
void this.sendExtensionMessage("updateSubFrameOffsetsForReflowEvent");
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -920,6 +934,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
|||||||
private clearUserInteractionEventTimeout() {
|
private clearUserInteractionEventTimeout() {
|
||||||
if (this.userInteractionEventTimeout) {
|
if (this.userInteractionEventTimeout) {
|
||||||
clearTimeout(this.userInteractionEventTimeout);
|
clearTimeout(this.userInteractionEventTimeout);
|
||||||
|
this.userInteractionEventTimeout = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -975,7 +990,6 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
|
|||||||
globalThis.addEventListener(EVENTS.MESSAGE, this.handleWindowMessageEvent);
|
globalThis.addEventListener(EVENTS.MESSAGE, this.handleWindowMessageEvent);
|
||||||
globalThis.document.addEventListener(EVENTS.VISIBILITYCHANGE, this.handleVisibilityChangeEvent);
|
globalThis.document.addEventListener(EVENTS.VISIBILITYCHANGE, this.handleVisibilityChangeEvent);
|
||||||
globalThis.addEventListener(EVENTS.FOCUSOUT, this.handleFormFieldBlurEvent);
|
globalThis.addEventListener(EVENTS.FOCUSOUT, this.handleFormFieldBlurEvent);
|
||||||
this.setupPageReflowEventListeners();
|
|
||||||
this.setOverlayRepositionEventListeners();
|
this.setOverlayRepositionEventListeners();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user