diff --git a/apps/browser/src/autofill/background/overlay-notifications.background.spec.ts b/apps/browser/src/autofill/background/overlay-notifications.background.spec.ts index d694438c00fb..1d4ff20b79af 100644 --- a/apps/browser/src/autofill/background/overlay-notifications.background.spec.ts +++ b/apps/browser/src/autofill/background/overlay-notifications.background.spec.ts @@ -164,8 +164,17 @@ describe("OverlayNotificationsBackground", () => { }); describe("storing the modified login form data", () => { + const pageDetails = mock({ fields: [mock()] }); const sender = mock({ tab: { id: 1 } }); + beforeEach(async () => { + sendMockExtensionMessage( + { command: "collectPageDetailsResponse", details: pageDetails }, + sender, + ); + await flushPromises(); + }); + it("stores the modified login cipher form data", async () => { sendMockExtensionMessage( { @@ -349,8 +358,14 @@ describe("OverlayNotificationsBackground", () => { describe("web requests that trigger notifications", () => { const requestId = "123345"; + const pageDetails = mock({ fields: [mock()] }); beforeEach(async () => { + sendMockExtensionMessage( + { command: "collectPageDetailsResponse", details: pageDetails }, + sender, + ); + await flushPromises(); sendMockExtensionMessage( { command: "formFieldSubmitted", @@ -446,6 +461,11 @@ describe("OverlayNotificationsBackground", () => { it("triggers the notification on the beforeRequest listener when a post-submission redirection is encountered", async () => { sender.tab = mock({ id: 4 }); + sendMockExtensionMessage( + { command: "collectPageDetailsResponse", details: pageDetails }, + sender, + ); + await flushPromises(); sendMockExtensionMessage( { command: "formFieldSubmitted", diff --git a/apps/browser/src/autofill/background/overlay-notifications.background.ts b/apps/browser/src/autofill/background/overlay-notifications.background.ts index ca8f05b77dc9..5ba3e388b7d5 100644 --- a/apps/browser/src/autofill/background/overlay-notifications.background.ts +++ b/apps/browser/src/autofill/background/overlay-notifications.background.ts @@ -24,6 +24,7 @@ export class OverlayNotificationsBackground implements OverlayNotificationsBackg private activeFormSubmissionRequests: ActiveFormSubmissionRequests = new Set(); private modifyLoginCipherFormData: ModifyLoginCipherFormDataForTab = new Map(); private clearLoginCipherFormDataSubject: Subject = new Subject(); + private notificationFallbackTimeout: number | NodeJS.Timeout | null; private readonly formSubmissionRequestMethods: Set = new Set(["POST", "PUT", "PATCH"]); private readonly extensionMessageHandlers: OverlayNotificationsExtensionMessageHandlers = { formFieldSubmitted: ({ message, sender }) => this.storeModifiedLoginFormData(message, sender), @@ -126,6 +127,10 @@ export class OverlayNotificationsBackground implements OverlayNotificationsBackg message: OverlayNotificationsExtensionMessage, sender: chrome.runtime.MessageSender, ) => { + if (!this.websiteOriginsWithFields.has(sender.tab.id)) { + return; + } + const { uri, username, password, newPassword } = message; if (!username && !password && !newPassword) { return; @@ -142,8 +147,29 @@ export class OverlayNotificationsBackground implements OverlayNotificationsBackg } this.modifyLoginCipherFormData.set(sender.tab.id, formData); + + this.clearNotificationFallbackTimeout(); + this.notificationFallbackTimeout = setTimeout( + () => + this.setupNotificationInitTrigger( + sender.tab.id, + "", + this.modifyLoginCipherFormData.get(sender.tab.id), + ).catch((error) => this.logService.error(error)), + 1500, + ); }; + /** + * Clears the timeout used when triggering a notification on click of the submit button. + */ + private clearNotificationFallbackTimeout() { + if (this.notificationFallbackTimeout) { + clearTimeout(this.notificationFallbackTimeout); + this.notificationFallbackTimeout = null; + } + } + /** * Determines if the sender of the message is from an excluded domain. This is used to prevent the * add login or change password notification from being triggered on the user's vault domain or @@ -306,12 +332,16 @@ export class OverlayNotificationsBackground implements OverlayNotificationsBackg private handleOnCompletedRequestEvent = async (details: chrome.webRequest.WebResponseDetails) => { if ( this.requestHostIsInvalid(details) || - isInvalidResponseStatusCode(details.statusCode) || !this.activeFormSubmissionRequests.has(details.requestId) ) { return; } + if (isInvalidResponseStatusCode(details.statusCode)) { + this.clearNotificationFallbackTimeout(); + return; + } + const modifyLoginData = this.modifyLoginCipherFormData.get(details.tabId); if (!modifyLoginData) { return; @@ -335,6 +365,8 @@ export class OverlayNotificationsBackground implements OverlayNotificationsBackg requestId: string, modifyLoginData: ModifyLoginCipherFormData, ) => { + this.clearNotificationFallbackTimeout(); + const tab = await BrowserApi.getTab(tabId); if (tab.status !== "complete") { await this.delayNotificationInitUntilTabIsComplete(tabId, requestId, modifyLoginData);