diff --git a/apps/browser/src/autofill/background/auto-submit-login.background.spec.ts b/apps/browser/src/autofill/background/auto-submit-login.background.spec.ts index 82a907a9e43..01767281a20 100644 --- a/apps/browser/src/autofill/background/auto-submit-login.background.spec.ts +++ b/apps/browser/src/autofill/background/auto-submit-login.background.spec.ts @@ -249,6 +249,20 @@ describe("AutoSubmitLoginBackground", () => { false, ); }); + + it("properly cleans up auto-submit workflows when requestInitiator is falsy but active auto-submit hosts exist", async () => { + webRequestDetails.initiator = undefined; + jest + .spyOn(BrowserApi, "getTab") + .mockResolvedValue(mock({ url: validAutoSubmitUrl, id: 1 })); + + triggerWebRequestOnBeforeRequestEvent(webRequestDetails); + await flushPromises(); + + expect(autoSubmitLoginBackground["validAutoSubmitHosts"].has(validAutoSubmitHost)).toBe( + false, + ); + }); }); describe("when the extension is running on a Safari browser", () => { diff --git a/apps/browser/src/autofill/background/auto-submit-login.background.ts b/apps/browser/src/autofill/background/auto-submit-login.background.ts index f593fab2516..07f0b98318a 100644 --- a/apps/browser/src/autofill/background/auto-submit-login.background.ts +++ b/apps/browser/src/autofill/background/auto-submit-login.background.ts @@ -1,5 +1,3 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore import { filter, firstValueFrom, of, switchMap } from "rxjs"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; @@ -64,6 +62,7 @@ export class AutoSubmitLoginBackground implements AutoSubmitLoginBackgroundAbstr this.policyService.policiesByType$(PolicyType.AutomaticAppLogIn, userId), ), getFirstPolicy, + filter((policy): policy is Policy => policy !== undefined), ) .subscribe(this.handleAutoSubmitLoginPolicySubscription.bind(this)); } @@ -165,7 +164,11 @@ export class AutoSubmitLoginBackground implements AutoSubmitLoginBackgroundAbstr details: chrome.webRequest.OnBeforeRequestDetails, ): undefined => { const requestInitiator = this.getRequestInitiator(details); - const isValidInitiator = this.isValidInitiator(requestInitiator); + if (!requestInitiator && this.validAutoSubmitHosts.size === 0) { + return; + } + + const isValidInitiator = requestInitiator ? this.isValidInitiator(requestInitiator) : false; if ( this.postRequestEncounteredAfterSubmission(details, isValidInitiator) || @@ -175,14 +178,20 @@ export class AutoSubmitLoginBackground implements AutoSubmitLoginBackgroundAbstr return; } - if (isValidInitiator && this.shouldRouteTriggerAutoSubmit(details, requestInitiator)) { + if ( + requestInitiator && + isValidInitiator && + this.shouldRouteTriggerAutoSubmit(details, requestInitiator) + ) { this.setupAutoSubmitFlow(details); return; } - this.disableAutoSubmitFlow(requestInitiator, details).catch((error) => - this.logService.error(error), - ); + if (requestInitiator || this.validAutoSubmitHosts.size > 0) { + this.disableAutoSubmitFlow(requestInitiator || "", details).catch((error) => + this.logService.error(error), + ); + } }; /** @@ -368,8 +377,9 @@ export class AutoSubmitLoginBackground implements AutoSubmitLoginBackgroundAbstr } const tab = await BrowserApi.getTab(details.tabId); - if (this.isValidAutoSubmitHost(tab?.url)) { - this.removeUrlFromAutoSubmitHosts(tab.url); + const tabUrl = tab?.url; + if (tabUrl && this.isValidAutoSubmitHost(tabUrl)) { + this.removeUrlFromAutoSubmitHosts(tabUrl); } }; @@ -427,7 +437,7 @@ export class AutoSubmitLoginBackground implements AutoSubmitLoginBackgroundAbstr */ private getUrlHost = (url: string) => { let parsedUrl = url; - if (!parsedUrl) { + if (!parsedUrl || typeof parsedUrl !== "string") { return ""; } @@ -495,6 +505,10 @@ export class AutoSubmitLoginBackground implements AutoSubmitLoginBackgroundAbstr message: AutoSubmitLoginMessage, sender: chrome.runtime.MessageSender, ) => { + if (sender.frameId == null || !sender.tab || !message.pageDetails) { + return; + } + await this.autofillService.doAutoFillOnTab( [ { @@ -515,7 +529,9 @@ export class AutoSubmitLoginBackground implements AutoSubmitLoginBackgroundAbstr * @param sender - The message sender. */ private handleMultiStepAutoSubmitLoginComplete = (sender: chrome.runtime.MessageSender) => { - this.removeUrlFromAutoSubmitHosts(sender.url); + if (sender.url) { + this.removeUrlFromAutoSubmitHosts(sender.url); + } }; /** @@ -526,7 +542,7 @@ export class AutoSubmitLoginBackground implements AutoSubmitLoginBackgroundAbstr */ private async initSafari() { const currentTab = await BrowserApi.getTabFromCurrentWindow(); - if (currentTab) { + if (currentTab?.url && currentTab.id != null && currentTab.id >= 0) { this.setMostRecentIdpHost(currentTab.url, currentTab.id); } @@ -558,7 +574,7 @@ export class AutoSubmitLoginBackground implements AutoSubmitLoginBackgroundAbstr } const tab = await BrowserApi.getTab(activeInfo.tabId); - if (tab) { + if (tab?.url && tab.id != null && tab.id >= 0) { this.setMostRecentIdpHost(tab.url, tab.id); } }; @@ -570,7 +586,7 @@ export class AutoSubmitLoginBackground implements AutoSubmitLoginBackgroundAbstr * @param changeInfo - The change information of the tab. */ private handleSafariTabOnUpdated = (tabId: number, changeInfo: chrome.tabs.OnUpdatedInfo) => { - if (changeInfo) { + if (changeInfo.url) { this.setMostRecentIdpHost(changeInfo.url, tabId); } }; @@ -626,13 +642,17 @@ export class AutoSubmitLoginBackground implements AutoSubmitLoginBackgroundAbstr * @param sender - The message sender. * @param sendResponse - The response callback. */ - private handleExtensionMessage = async ( + private handleExtensionMessage = ( message: AutoSubmitLoginMessage, sender: chrome.runtime.MessageSender, sendResponse: (response?: any) => void, ) => { const { tab, url } = sender; - if (tab?.id !== this.currentAutoSubmitHostData.tabId || !this.isValidAutoSubmitHost(url)) { + if ( + !url || + tab?.id !== this.currentAutoSubmitHostData.tabId || + !this.isValidAutoSubmitHost(url) + ) { return null; } diff --git a/apps/browser/src/platform/browser/browser-api.ts b/apps/browser/src/platform/browser/browser-api.ts index cfc39fa18a1..feefd527636 100644 --- a/apps/browser/src/platform/browser/browser-api.ts +++ b/apps/browser/src/platform/browser/browser-api.ts @@ -560,7 +560,8 @@ export class BrowserApi { * @param event - The event in which to remove the listener from. * @param callback - The callback you want removed from the event. */ - static removeListener unknown>( + // Chrome's Event.removeListener expects callback args as `any[]` to align with its internal event typings. + static removeListener any>( event: chrome.events.Event, callback: T, ) {