1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-15 07:43:35 +00:00

[PM-18219] Normalize blocked domain checks to a common util (#13416)

* normalize blocked domain checks to common util

* do not use currentTabIsOnBlocklist$ in showCurrentTabIsBlockedBanner$ resolution

* update additional vault popup autofill service cases to use isUrlInList

* cleanup and use Utils get hostname instead of tldts directly
This commit is contained in:
Jonathan Prusik
2025-02-21 13:15:02 -05:00
committed by GitHub
parent 0bc7813b1c
commit 2e96405f15
5 changed files with 145 additions and 45 deletions

View File

@@ -70,6 +70,7 @@ import {
UserNotificationSettingsService,
UserNotificationSettingsServiceAbstraction,
} from "@bitwarden/common/autofill/services/user-notification-settings.service";
import { isUrlInList } from "@bitwarden/common/autofill/utils";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { DefaultBillingAccountProfileStateService } from "@bitwarden/common/billing/services/account/billing-account-profile-state.service";
import { ClientType } from "@bitwarden/common/enums";
@@ -1384,18 +1385,11 @@ export default class MainBackground {
const tab = await BrowserApi.getTabFromCurrentWindow();
if (tab) {
const currentUriIsBlocked = await firstValueFrom(
const currentUrlIsBlocked = await firstValueFrom(
this.domainSettingsService.blockedInteractionsUris$.pipe(
map((blockedInteractionsUris) => {
if (blockedInteractionsUris && tab?.url?.length) {
const tabURL = new URL(tab.url);
const tabIsBlocked = Object.keys(blockedInteractionsUris).some((blockedHostname) =>
tabURL.hostname.endsWith(blockedHostname),
);
if (tabIsBlocked) {
return true;
}
map((blockedInteractionsUrls) => {
if (blockedInteractionsUrls && tab?.url?.length) {
return isUrlInList(tab.url, blockedInteractionsUrls);
}
return false;
@@ -1403,7 +1397,7 @@ export default class MainBackground {
),
);
await this.cipherContextMenuHandler?.update(tab.url, currentUriIsBlocked);
await this.cipherContextMenuHandler?.update(tab.url, currentUrlIsBlocked);
this.onUpdatedRan = this.onReplacedRan = false;
}
}

View File

@@ -1,6 +1,7 @@
import { firstValueFrom } from "rxjs";
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
import { isUrlInList } from "@bitwarden/common/autofill/utils";
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@@ -39,23 +40,20 @@ export class BrowserScriptInjectorService extends ScriptInjectorService {
}
const tab = tabId && (await BrowserApi.getTab(tabId));
const tabURL = tab?.url ? new URL(tab.url) : null;
// Check if the tab URI is on the disabled URIs list
// Check if the tab URL is on the disabled URLs list
let injectionAllowedInTab = true;
const blockedDomains = await firstValueFrom(
this.domainSettingsService.blockedInteractionsUris$,
);
if (blockedDomains && tabURL?.hostname) {
const blockedDomainsSet = new Set(Object.keys(blockedDomains));
injectionAllowedInTab = !(tabURL && blockedDomainsSet.has(tabURL.hostname));
if (blockedDomains && tab?.url) {
injectionAllowedInTab = !isUrlInList(tab?.url, blockedDomains);
}
if (!injectionAllowedInTab) {
this.logService.warning(
`${injectDetails.file} was not injected because ${tabURL?.hostname || "the tab URI"} is on the user's blocked domains list.`,
`${injectDetails.file} was not injected because ${tab?.url || "the tab URL"} is on the user's blocked domains list.`,
);
return;
}

View File

@@ -16,10 +16,12 @@ import {
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
import { isUrlInList } from "@bitwarden/common/autofill/utils";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { CipherRepromptType, CipherType } from "@bitwarden/common/vault/enums";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
@@ -70,14 +72,9 @@ export class VaultPopupAutofillService {
this.domainSettingsService.blockedInteractionsUris$,
this.currentAutofillTab$,
]).pipe(
map(([blockedInteractionsUris, currentTab]) => {
if (blockedInteractionsUris && currentTab?.url?.length) {
const tabURL = new URL(currentTab.url);
const tabIsBlocked = Object.keys(blockedInteractionsUris).includes(tabURL.hostname);
if (tabIsBlocked) {
return true;
}
map(([blockedInteractionsUrls, currentTab]) => {
if (blockedInteractionsUrls && currentTab) {
return isUrlInList(currentTab?.url, blockedInteractionsUrls);
}
return false;
@@ -89,13 +86,18 @@ export class VaultPopupAutofillService {
this.domainSettingsService.blockedInteractionsUris$,
this.currentAutofillTab$,
]).pipe(
map(([blockedInteractionsUris, currentTab]) => {
if (blockedInteractionsUris && currentTab?.url?.length) {
const tabURL = new URL(currentTab.url);
const tabIsBlocked = Object.keys(blockedInteractionsUris).includes(tabURL.hostname);
map(([blockedInteractionsUrls, currentTab]) => {
if (blockedInteractionsUrls && currentTab?.url?.length) {
const tabHostname = Utils.getHostname(currentTab.url);
if (!tabHostname) {
return false;
}
const tabIsBlocked = isUrlInList(currentTab.url, blockedInteractionsUrls);
const showScriptInjectionIsBlockedBanner =
tabIsBlocked && !blockedInteractionsUris[tabURL.hostname]?.bannerIsDismissed;
tabIsBlocked && !blockedInteractionsUrls[tabHostname]?.bannerIsDismissed;
return showScriptInjectionIsBlockedBanner;
}
@@ -108,20 +110,22 @@ export class VaultPopupAutofillService {
async dismissCurrentTabIsBlockedBanner() {
try {
const currentTab = await firstValueFrom(this.currentAutofillTab$);
const currentTabURL = currentTab?.url.length && new URL(currentTab.url);
const currentTabHostname = currentTabURL && currentTabURL.hostname;
const currentTabHostname = currentTab?.url.length && Utils.getHostname(currentTab.url);
if (!currentTabHostname) {
return;
}
const blockedURIs = await firstValueFrom(this.domainSettingsService.blockedInteractionsUris$);
const tabIsBlocked = Object.keys(blockedURIs).includes(currentTabHostname);
const blockedURLs = await firstValueFrom(this.domainSettingsService.blockedInteractionsUris$);
let tabIsBlocked = false;
if (blockedURLs && currentTab?.url?.length) {
tabIsBlocked = isUrlInList(currentTab.url, blockedURLs);
}
if (tabIsBlocked) {
void this.domainSettingsService.setBlockedInteractionsUris({
...blockedURIs,
...blockedURLs,
[currentTabHostname as string]: { bannerIsDismissed: true },
});
}
@@ -129,7 +133,7 @@ export class VaultPopupAutofillService {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
throw new Error(
"There was a problem dismissing the blocked interaction URI notification banner",
"There was a problem dismissing the blocked interaction URL notification banner",
);
}
}
@@ -147,11 +151,9 @@ export class VaultPopupAutofillService {
}
return this.domainSettingsService.blockedInteractionsUris$.pipe(
switchMap((blockedURIs) => {
// This blocked URI logic will be updated to use the common util in PM-18219
if (blockedURIs && tab?.url?.length) {
const tabURL = new URL(tab.url);
const tabIsBlocked = Object.keys(blockedURIs).includes(tabURL.hostname);
switchMap((blockedURLs) => {
if (blockedURLs && tab?.url?.length) {
const tabIsBlocked = isUrlInList(tab.url, blockedURLs);
if (tabIsBlocked) {
return of([]);