mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 16:53:34 +00:00
update tests and cleanup
This commit is contained in:
@@ -15,7 +15,6 @@ import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
|
||||
import { NeverDomains } from "@bitwarden/common/models/domain/domain-service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import {
|
||||
ButtonModule,
|
||||
@@ -26,6 +25,7 @@ import {
|
||||
LinkModule,
|
||||
SectionComponent,
|
||||
SectionHeaderComponent,
|
||||
ToastService,
|
||||
TypographyModule,
|
||||
} from "@bitwarden/components";
|
||||
|
||||
@@ -59,7 +59,8 @@ import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.co
|
||||
],
|
||||
})
|
||||
export class BlockedDomainsComponent implements AfterViewInit, OnDestroy {
|
||||
@ViewChildren("uriInput") uriInputElements: QueryList<ElementRef<HTMLInputElement>>;
|
||||
@ViewChildren("uriInput") uriInputElements: QueryList<ElementRef<HTMLInputElement>> =
|
||||
new QueryList();
|
||||
|
||||
dataIsPristine = true;
|
||||
isLoading = false;
|
||||
@@ -73,7 +74,7 @@ export class BlockedDomainsComponent implements AfterViewInit, OnDestroy {
|
||||
constructor(
|
||||
private domainSettingsService: DomainSettingsService,
|
||||
private i18nService: I18nService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
async ngAfterViewInit() {
|
||||
@@ -150,11 +151,11 @@ export class BlockedDomainsComponent implements AfterViewInit, OnDestroy {
|
||||
const validatedHost = Utils.getHostname(uri);
|
||||
|
||||
if (!validatedHost) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
null,
|
||||
this.i18nService.t("excludedDomainsInvalidDomain", uri),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
message: this.i18nService.t("excludedDomainsInvalidDomain", uri),
|
||||
title: "",
|
||||
variant: "error",
|
||||
});
|
||||
|
||||
// Don't reset via `handleStateUpdate` to allow existing input value correction
|
||||
this.isLoading = false;
|
||||
@@ -176,7 +177,7 @@ export class BlockedDomainsComponent implements AfterViewInit, OnDestroy {
|
||||
if (stateIsUnchanged) {
|
||||
// Reset UI state directly
|
||||
const constructedNeverDomainsState = this.storedBlockedDomains.reduce(
|
||||
(neverDomains, uri) => ({ ...neverDomains, [uri]: null }),
|
||||
(neverDomains: NeverDomains, uri: string) => ({ ...neverDomains, [uri]: null }),
|
||||
{},
|
||||
);
|
||||
this.handleStateUpdate(constructedNeverDomainsState);
|
||||
@@ -184,13 +185,17 @@ export class BlockedDomainsComponent implements AfterViewInit, OnDestroy {
|
||||
await this.domainSettingsService.setBlockedInteractionsUris(newBlockedDomainsSaveState);
|
||||
}
|
||||
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("blockedDomainsSavedSuccess"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
message: this.i18nService.t("blockedDomainsSavedSuccess"),
|
||||
title: "",
|
||||
variant: "success",
|
||||
});
|
||||
} catch {
|
||||
this.platformUtilsService.showToast("error", null, this.i18nService.t("unexpectedError"));
|
||||
this.toastService.showToast({
|
||||
message: this.i18nService.t("unexpectedError"),
|
||||
title: "",
|
||||
variant: "error",
|
||||
});
|
||||
|
||||
// Don't reset via `handleStateUpdate` to preserve input values
|
||||
this.isLoading = false;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { CommonModule } from "@angular/common";
|
||||
import {
|
||||
QueryList,
|
||||
@@ -17,7 +15,6 @@ import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
|
||||
import { NeverDomains } from "@bitwarden/common/models/domain/domain-service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import {
|
||||
ButtonModule,
|
||||
@@ -28,6 +25,7 @@ import {
|
||||
LinkModule,
|
||||
SectionComponent,
|
||||
SectionHeaderComponent,
|
||||
ToastService,
|
||||
TypographyModule,
|
||||
} from "@bitwarden/components";
|
||||
|
||||
@@ -62,7 +60,8 @@ import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.co
|
||||
],
|
||||
})
|
||||
export class ExcludedDomainsComponent implements AfterViewInit, OnDestroy {
|
||||
@ViewChildren("uriInput") uriInputElements: QueryList<ElementRef<HTMLInputElement>>;
|
||||
@ViewChildren("uriInput") uriInputElements: QueryList<ElementRef<HTMLInputElement>> =
|
||||
new QueryList();
|
||||
|
||||
accountSwitcherEnabled = false;
|
||||
dataIsPristine = true;
|
||||
@@ -77,7 +76,7 @@ export class ExcludedDomainsComponent implements AfterViewInit, OnDestroy {
|
||||
constructor(
|
||||
private domainSettingsService: DomainSettingsService,
|
||||
private i18nService: I18nService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private toastService: ToastService,
|
||||
) {
|
||||
this.accountSwitcherEnabled = enableAccountSwitching();
|
||||
}
|
||||
@@ -156,11 +155,11 @@ export class ExcludedDomainsComponent implements AfterViewInit, OnDestroy {
|
||||
const validatedHost = Utils.getHostname(uri);
|
||||
|
||||
if (!validatedHost) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
null,
|
||||
this.i18nService.t("excludedDomainsInvalidDomain", uri),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
message: this.i18nService.t("excludedDomainsInvalidDomain", uri),
|
||||
title: "",
|
||||
variant: "error",
|
||||
});
|
||||
|
||||
// Don't reset via `handleStateUpdate` to allow existing input value correction
|
||||
this.isLoading = false;
|
||||
@@ -182,7 +181,7 @@ export class ExcludedDomainsComponent implements AfterViewInit, OnDestroy {
|
||||
if (stateIsUnchanged) {
|
||||
// Reset UI state directly
|
||||
const constructedNeverDomainsState = this.storedExcludedDomains.reduce(
|
||||
(neverDomains, uri) => ({ ...neverDomains, [uri]: null }),
|
||||
(neverDomains: NeverDomains, uri: string) => ({ ...neverDomains, [uri]: null }),
|
||||
{},
|
||||
);
|
||||
this.handleStateUpdate(constructedNeverDomainsState);
|
||||
@@ -190,13 +189,17 @@ export class ExcludedDomainsComponent implements AfterViewInit, OnDestroy {
|
||||
await this.domainSettingsService.setNeverDomains(newExcludedDomainsSaveState);
|
||||
}
|
||||
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("excludedDomainsSavedSuccess"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
message: this.i18nService.t("excludedDomainsSavedSuccess"),
|
||||
title: "",
|
||||
variant: "success",
|
||||
});
|
||||
} catch {
|
||||
this.platformUtilsService.showToast("error", null, this.i18nService.t("unexpectedError"));
|
||||
this.toastService.showToast({
|
||||
message: this.i18nService.t("unexpectedError"),
|
||||
title: "",
|
||||
variant: "error",
|
||||
});
|
||||
|
||||
// Don't reset via `handleStateUpdate` to preserve input values
|
||||
this.isLoading = false;
|
||||
|
||||
@@ -98,6 +98,8 @@ describe("AutofillService", () => {
|
||||
let messageListener: MockProxy<MessageListener>;
|
||||
|
||||
beforeEach(() => {
|
||||
configService = mock<ConfigService>();
|
||||
configService.getFeatureFlag$.mockImplementation(() => of(false));
|
||||
scriptInjectorService = new BrowserScriptInjectorService(
|
||||
domainSettingsService,
|
||||
platformUtilsService,
|
||||
@@ -110,10 +112,10 @@ describe("AutofillService", () => {
|
||||
autofillSettingsService.inlineMenuVisibility$ = inlineMenuVisibilityMock$;
|
||||
autofillSettingsService.showInlineMenuCards$ = showInlineMenuCardsMock$;
|
||||
autofillSettingsService.showInlineMenuIdentities$ = showInlineMenuIdentitiesMock$;
|
||||
autofillSettingsService.autofillOnPageLoad$ = of(true);
|
||||
activeAccountStatusMock$ = new BehaviorSubject(AuthenticationStatus.Unlocked);
|
||||
authService = mock<AuthService>();
|
||||
authService.activeAccountStatus$ = activeAccountStatusMock$;
|
||||
configService = mock<ConfigService>();
|
||||
messageListener = mock<MessageListener>();
|
||||
enableChangedPasswordPromptMock$ = new BehaviorSubject(true);
|
||||
enableAddedLoginPromptMock$ = new BehaviorSubject(true);
|
||||
@@ -389,6 +391,7 @@ describe("AutofillService", () => {
|
||||
);
|
||||
tabMock = createChromeTabMock();
|
||||
sender = { tab: tabMock, frameId: 1 };
|
||||
jest.spyOn(BrowserApi, "getTab").mockImplementation(async () => tabMock);
|
||||
jest.spyOn(BrowserApi, "executeScriptInTab").mockImplementation();
|
||||
jest
|
||||
.spyOn(autofillService, "getInlineMenuVisibility")
|
||||
|
||||
@@ -1,9 +1,22 @@
|
||||
import { mock } from "jest-mock-extended";
|
||||
import { mock, MockProxy } from "jest-mock-extended";
|
||||
import { of } from "rxjs";
|
||||
|
||||
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
|
||||
import {
|
||||
DomainSettingsService,
|
||||
DefaultDomainSettingsService,
|
||||
} from "@bitwarden/common/autofill/services/domain-settings.service";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import {
|
||||
FakeStateProvider,
|
||||
FakeAccountService,
|
||||
mockAccountServiceWith,
|
||||
} from "@bitwarden/common/spec";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
|
||||
import { createChromeTabMock } from "../../autofill/spec/autofill-mocks";
|
||||
import { BrowserApi } from "../browser/browser-api";
|
||||
|
||||
import {
|
||||
@@ -12,8 +25,19 @@ import {
|
||||
} from "./abstractions/script-injector.service";
|
||||
import { BrowserScriptInjectorService } from "./browser-script-injector.service";
|
||||
|
||||
const mockEquivalentDomains = [
|
||||
["example.com", "exampleapp.com", "example.co.uk", "ejemplo.es"],
|
||||
["bitwarden.com", "bitwarden.co.uk", "sm-bitwarden.com"],
|
||||
["example.co.uk", "exampleapp.co.uk"],
|
||||
];
|
||||
|
||||
describe("ScriptInjectorService", () => {
|
||||
const tabId = 1;
|
||||
const tabMock = createChromeTabMock({ id: tabId });
|
||||
const mockBlockedURI = new URL(tabMock.url);
|
||||
jest.spyOn(BrowserApi, "executeScriptInTab").mockImplementation();
|
||||
jest.spyOn(BrowserApi, "isManifestVersion");
|
||||
|
||||
const combinedManifestVersionFile = "content/autofill-init.js";
|
||||
const mv2SpecificFile = "content/autofill-init-mv2.js";
|
||||
const mv2Details = { file: mv2SpecificFile };
|
||||
@@ -23,14 +47,24 @@ describe("ScriptInjectorService", () => {
|
||||
runAt: "document_start",
|
||||
};
|
||||
const manifestVersionSpy = jest.spyOn(BrowserApi, "manifestVersion", "get");
|
||||
|
||||
let scriptInjectorService: BrowserScriptInjectorService;
|
||||
jest.spyOn(BrowserApi, "executeScriptInTab").mockImplementation();
|
||||
jest.spyOn(BrowserApi, "isManifestVersion");
|
||||
const domainSettingsService = mock<DomainSettingsService>();
|
||||
const platformUtilsService = mock<PlatformUtilsService>();
|
||||
const logService = mock<LogService>();
|
||||
const platformUtilsService = mock<PlatformUtilsService>();
|
||||
const mockUserId = Utils.newGuid() as UserId;
|
||||
const accountService: FakeAccountService = mockAccountServiceWith(mockUserId);
|
||||
const fakeStateProvider: FakeStateProvider = new FakeStateProvider(accountService);
|
||||
let configService: MockProxy<ConfigService>;
|
||||
let domainSettingsService: DomainSettingsService;
|
||||
const expectedBlockedURIError = new Error("This URI of this tab is on the blocked domains list.");
|
||||
|
||||
beforeEach(() => {
|
||||
jest.spyOn(BrowserApi, "getTab").mockImplementation(async () => tabMock);
|
||||
configService = mock<ConfigService>();
|
||||
configService.getFeatureFlag$.mockImplementation(() => of(false));
|
||||
domainSettingsService = new DefaultDomainSettingsService(fakeStateProvider, configService);
|
||||
domainSettingsService.equivalentDomains$ = of(mockEquivalentDomains);
|
||||
domainSettingsService.blockedInteractionsUris$ = of(null);
|
||||
scriptInjectorService = new BrowserScriptInjectorService(
|
||||
domainSettingsService,
|
||||
platformUtilsService,
|
||||
@@ -77,6 +111,76 @@ describe("ScriptInjectorService", () => {
|
||||
{ world: "ISOLATED" },
|
||||
);
|
||||
});
|
||||
|
||||
it("skips injecting the script in manifest v3 when the tab domain is a blocked domain", async () => {
|
||||
domainSettingsService.blockedInteractionsUris$ = of({ [mockBlockedURI.host]: null });
|
||||
manifestVersionSpy.mockReturnValue(3);
|
||||
|
||||
await expect(
|
||||
scriptInjectorService.inject({
|
||||
tabId,
|
||||
injectDetails: {
|
||||
file: combinedManifestVersionFile,
|
||||
frame: 10,
|
||||
...sharedInjectDetails,
|
||||
},
|
||||
}),
|
||||
).rejects.toThrow(expectedBlockedURIError);
|
||||
});
|
||||
|
||||
it("skips injecting the script in manifest v2 when the tab domain is a blocked domain", async () => {
|
||||
domainSettingsService.blockedInteractionsUris$ = of({ [mockBlockedURI.host]: null });
|
||||
manifestVersionSpy.mockReturnValue(2);
|
||||
|
||||
await expect(
|
||||
scriptInjectorService.inject({
|
||||
tabId,
|
||||
injectDetails: {
|
||||
file: combinedManifestVersionFile,
|
||||
frame: "all_frames",
|
||||
...sharedInjectDetails,
|
||||
},
|
||||
}),
|
||||
).rejects.toThrow(expectedBlockedURIError);
|
||||
});
|
||||
|
||||
it("injects the script in manifest v2 when given combined injection details", async () => {
|
||||
manifestVersionSpy.mockReturnValue(2);
|
||||
|
||||
await scriptInjectorService.inject({
|
||||
tabId,
|
||||
injectDetails: {
|
||||
file: combinedManifestVersionFile,
|
||||
frame: "all_frames",
|
||||
...sharedInjectDetails,
|
||||
},
|
||||
});
|
||||
|
||||
expect(BrowserApi.executeScriptInTab).toHaveBeenCalledWith(tabId, {
|
||||
...sharedInjectDetails,
|
||||
allFrames: true,
|
||||
file: combinedManifestVersionFile,
|
||||
});
|
||||
});
|
||||
|
||||
it("injects the script in manifest v3 when given combined injection details", async () => {
|
||||
manifestVersionSpy.mockReturnValue(3);
|
||||
|
||||
await scriptInjectorService.inject({
|
||||
tabId,
|
||||
injectDetails: {
|
||||
file: combinedManifestVersionFile,
|
||||
frame: 10,
|
||||
...sharedInjectDetails,
|
||||
},
|
||||
});
|
||||
|
||||
expect(BrowserApi.executeScriptInTab).toHaveBeenCalledWith(
|
||||
tabId,
|
||||
{ ...sharedInjectDetails, frameId: 10, file: combinedManifestVersionFile },
|
||||
{ world: "ISOLATED" },
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("injection of mv2 specific details", () => {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Subject, takeUntil } from "rxjs";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
|
||||
import { NeverDomains } from "@bitwarden/common/models/domain/domain-service";
|
||||
// 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";
|
||||
@@ -18,22 +17,12 @@ import {
|
||||
export class BrowserScriptInjectorService extends ScriptInjectorService {
|
||||
blockedDomains: Set<string> = null;
|
||||
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
constructor(
|
||||
private readonly domainSettingsService: DomainSettingsService,
|
||||
private readonly platformUtilsService: PlatformUtilsService,
|
||||
private readonly logService: LogService,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.domainSettingsService.blockedInteractionsUris$
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((neverDomains: NeverDomains) => {
|
||||
if (neverDomains) {
|
||||
this.blockedDomains = new Set(Object.keys(neverDomains));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,10 +38,20 @@ export class BrowserScriptInjectorService extends ScriptInjectorService {
|
||||
throw new Error("No file specified for script injection");
|
||||
}
|
||||
|
||||
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
|
||||
const tab = await BrowserApi.getTab(tabId);
|
||||
const tabURL = tab.url ? new URL(tab.url) : null;
|
||||
const injectionAllowedInTab = !(tabURL && this.blockedDomains?.has(tabURL.hostname));
|
||||
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 (!injectionAllowedInTab) {
|
||||
throw new Error("This URI of this tab is on the blocked domains list.");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { mock } from "jest-mock-extended";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
import { firstValueFrom, of } from "rxjs";
|
||||
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/services/policy/policy.service";
|
||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||
@@ -45,8 +45,10 @@ describe("FilelessImporterBackground ", () => {
|
||||
const platformUtilsService = mock<PlatformUtilsService>();
|
||||
const logService = mock<LogService>();
|
||||
let scriptInjectorService: BrowserScriptInjectorService;
|
||||
let tabMock: chrome.tabs.Tab;
|
||||
|
||||
beforeEach(() => {
|
||||
domainSettingsService.blockedInteractionsUris$ = of(null);
|
||||
scriptInjectorService = new BrowserScriptInjectorService(
|
||||
domainSettingsService,
|
||||
platformUtilsService,
|
||||
@@ -81,12 +83,13 @@ describe("FilelessImporterBackground ", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
lpImporterPort = createPortSpyMock(FilelessImportPort.LpImporter);
|
||||
tabMock = lpImporterPort.sender.tab;
|
||||
jest.spyOn(BrowserApi, "getTab").mockImplementation(async () => tabMock);
|
||||
manifestVersionSpy = jest.spyOn(BrowserApi, "manifestVersion", "get");
|
||||
executeScriptInTabSpy = jest.spyOn(BrowserApi, "executeScriptInTab").mockResolvedValue(null);
|
||||
jest.spyOn(authService, "getAuthStatus").mockResolvedValue(AuthenticationStatus.Unlocked);
|
||||
jest.spyOn(configService, "getFeatureFlag").mockResolvedValue(true);
|
||||
jest.spyOn(filelessImporterBackground as any, "removeIndividualVault");
|
||||
(firstValueFrom as jest.Mock).mockResolvedValue(false);
|
||||
});
|
||||
|
||||
it("ignores the port connection if the port name is not present in the set of filelessImportNames", async () => {
|
||||
@@ -99,6 +102,7 @@ describe("FilelessImporterBackground ", () => {
|
||||
});
|
||||
|
||||
it("posts a message to the port indicating that the fileless import feature is disabled if the user's auth status is not unlocked", async () => {
|
||||
(firstValueFrom as jest.Mock).mockResolvedValue(false);
|
||||
jest.spyOn(authService, "getAuthStatus").mockResolvedValue(AuthenticationStatus.Locked);
|
||||
|
||||
triggerRuntimeOnConnectEvent(lpImporterPort);
|
||||
@@ -135,6 +139,7 @@ describe("FilelessImporterBackground ", () => {
|
||||
});
|
||||
|
||||
it("posts a message to the port indicating that the fileless import feature is enabled", async () => {
|
||||
(firstValueFrom as jest.Mock).mockResolvedValue(false);
|
||||
triggerRuntimeOnConnectEvent(lpImporterPort);
|
||||
await flushPromises();
|
||||
|
||||
@@ -158,6 +163,7 @@ describe("FilelessImporterBackground ", () => {
|
||||
});
|
||||
|
||||
it("triggers an injection of the `lp-suppress-import-download-script-append-mv2.js` script in manifest v2", async () => {
|
||||
(firstValueFrom as jest.Mock).mockResolvedValueOnce(false);
|
||||
manifestVersionSpy.mockReturnValue(2);
|
||||
|
||||
triggerRuntimeOnConnectEvent(lpImporterPort);
|
||||
|
||||
@@ -44,7 +44,7 @@ export class AutofillVaultListItemsComponent implements OnInit {
|
||||
/**
|
||||
* Indicators for the section.
|
||||
*/
|
||||
@Input() sectionIndicators: string[];
|
||||
@Input() sectionIndicators: string[] = [];
|
||||
|
||||
/**
|
||||
* Observable that determines whether the empty autofill tip should be shown.
|
||||
|
||||
@@ -103,7 +103,7 @@ export class VaultListItemsContainerComponent implements AfterViewInit {
|
||||
/**
|
||||
* Indicators for the section.
|
||||
*/
|
||||
@Input() sectionIndicators: string[];
|
||||
@Input() sectionIndicators: string[] = [];
|
||||
|
||||
/**
|
||||
* Optional description for the vault list item section. Will be shown below the title even when
|
||||
|
||||
@@ -62,7 +62,7 @@ export class VaultV2Component implements OnInit, OnDestroy {
|
||||
protected loading$ = this.vaultPopupItemsService.loading$;
|
||||
protected scriptInjectionIsBlocked = false;
|
||||
protected showScriptInjectionIsBlockedBanner = false;
|
||||
protected autofillTabHostname: string = null;
|
||||
protected autofillTabHostname: string | null = null;
|
||||
protected sectionIndicators: string[] = [];
|
||||
|
||||
protected newItemItemValues$: Observable<NewItemInitialValues> =
|
||||
@@ -151,20 +151,24 @@ export class VaultV2Component implements OnInit, OnDestroy {
|
||||
ngOnDestroy(): void {}
|
||||
|
||||
handleScriptInjectionIsBlockedBannerDismiss() {
|
||||
firstValueFrom(this.domainSettingsService.blockedInteractionsUris$)
|
||||
.then((blockedURIs) => {
|
||||
this.showScriptInjectionIsBlockedBanner = false;
|
||||
this.domainSettingsService
|
||||
.setBlockedInteractionsUris({
|
||||
if (!this.autofillTabHostname) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
void firstValueFrom(this.domainSettingsService.blockedInteractionsUris$).then(
|
||||
(blockedURIs) => {
|
||||
this.showScriptInjectionIsBlockedBanner = false;
|
||||
void this.domainSettingsService.setBlockedInteractionsUris({
|
||||
...blockedURIs,
|
||||
[this.autofillTabHostname]: { bannerIsDismissed: true },
|
||||
})
|
||||
.catch(() => {
|
||||
/* no-op */
|
||||
[this.autofillTabHostname as string]: { bannerIsDismissed: true },
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
/* no-op */
|
||||
});
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
"There was a problem dismissing the blocked interaction URI notification banner",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -483,7 +483,29 @@ export class ServiceContainer {
|
||||
|
||||
this.containerService = new ContainerService(this.keyService, this.encryptService);
|
||||
|
||||
this.domainSettingsService = new DefaultDomainSettingsService(this.stateProvider);
|
||||
this.configApiService = new ConfigApiService(this.apiService, this.tokenService);
|
||||
|
||||
this.authService = new AuthService(
|
||||
this.accountService,
|
||||
this.messagingService,
|
||||
this.keyService,
|
||||
this.apiService,
|
||||
this.stateService,
|
||||
this.tokenService,
|
||||
);
|
||||
|
||||
this.configService = new DefaultConfigService(
|
||||
this.configApiService,
|
||||
this.environmentService,
|
||||
this.logService,
|
||||
this.stateProvider,
|
||||
this.authService,
|
||||
);
|
||||
|
||||
this.domainSettingsService = new DefaultDomainSettingsService(
|
||||
this.stateProvider,
|
||||
this.configService,
|
||||
);
|
||||
|
||||
this.fileUploadService = new FileUploadService(this.logService, this.apiService);
|
||||
|
||||
@@ -579,25 +601,6 @@ export class ServiceContainer {
|
||||
|
||||
this.taskSchedulerService = new DefaultTaskSchedulerService(this.logService);
|
||||
|
||||
this.authService = new AuthService(
|
||||
this.accountService,
|
||||
this.messagingService,
|
||||
this.keyService,
|
||||
this.apiService,
|
||||
this.stateService,
|
||||
this.tokenService,
|
||||
);
|
||||
|
||||
this.configApiService = new ConfigApiService(this.apiService, this.tokenService);
|
||||
|
||||
this.configService = new DefaultConfigService(
|
||||
this.configApiService,
|
||||
this.environmentService,
|
||||
this.logService,
|
||||
this.stateProvider,
|
||||
this.authService,
|
||||
);
|
||||
|
||||
this.devicesApiService = new DevicesApiServiceImplementation(this.apiService);
|
||||
this.deviceTrustService = new DeviceTrustService(
|
||||
this.keyGenerationService,
|
||||
|
||||
@@ -463,6 +463,11 @@ const safeProviders: SafeProvider[] = [
|
||||
useClass: CipherFileUploadService,
|
||||
deps: [ApiServiceAbstraction, FileUploadServiceAbstraction],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: DomainSettingsService,
|
||||
useClass: DefaultDomainSettingsService,
|
||||
deps: [StateProvider, ConfigService],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: CipherServiceAbstraction,
|
||||
useFactory: (
|
||||
@@ -1243,11 +1248,6 @@ const safeProviders: SafeProvider[] = [
|
||||
useClass: BadgeSettingsService,
|
||||
deps: [StateProvider],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: DomainSettingsService,
|
||||
useClass: DefaultDomainSettingsService,
|
||||
deps: [StateProvider, ConfigService],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: BiometricStateService,
|
||||
useClass: DefaultBiometricStateService,
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { MockProxy, mock } from "jest-mock-extended";
|
||||
import { firstValueFrom, of } from "rxjs";
|
||||
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
|
||||
import { FakeStateProvider, FakeAccountService, mockAccountServiceWith } from "../../../spec";
|
||||
import { Utils } from "../../platform/misc/utils";
|
||||
import { UserId } from "../../types/guid";
|
||||
@@ -8,8 +11,10 @@ import { DefaultDomainSettingsService, DomainSettingsService } from "./domain-se
|
||||
|
||||
describe("DefaultDomainSettingsService", () => {
|
||||
let domainSettingsService: DomainSettingsService;
|
||||
const configServiceMock = mock<ConfigService>();
|
||||
const mockUserId = Utils.newGuid() as UserId;
|
||||
const accountService: FakeAccountService = mockAccountServiceWith(mockUserId);
|
||||
let mockConfigService: MockProxy<ConfigService>;
|
||||
const fakeStateProvider: FakeStateProvider = new FakeStateProvider(accountService);
|
||||
|
||||
const mockEquivalentDomains = [
|
||||
@@ -19,10 +24,12 @@ describe("DefaultDomainSettingsService", () => {
|
||||
];
|
||||
|
||||
beforeEach(() => {
|
||||
domainSettingsService = new DefaultDomainSettingsService(fakeStateProvider);
|
||||
domainSettingsService = new DefaultDomainSettingsService(fakeStateProvider, mockConfigService);
|
||||
jest.spyOn(configServiceMock, "getFeatureFlag$").mockReturnValue(of(false));
|
||||
|
||||
jest.spyOn(domainSettingsService, "getUrlEquivalentDomains");
|
||||
domainSettingsService.equivalentDomains$ = of(mockEquivalentDomains);
|
||||
domainSettingsService.blockedInteractionsUris$ = of(null);
|
||||
});
|
||||
|
||||
describe("getUrlEquivalentDomains", () => {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import { combineLatest, map, Observable } from "rxjs";
|
||||
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
|
||||
import {
|
||||
NeverDomains,
|
||||
@@ -11,6 +10,7 @@ import {
|
||||
UriMatchStrategySetting,
|
||||
UriMatchStrategy,
|
||||
} from "../../models/domain/domain-service";
|
||||
import { ConfigService } from "../../platform/abstractions/config/config.service";
|
||||
import { Utils } from "../../platform/misc/utils";
|
||||
import {
|
||||
DOMAIN_SETTINGS_DISK,
|
||||
@@ -99,7 +99,7 @@ export class DefaultDomainSettingsService implements DomainSettingsService {
|
||||
|
||||
this.blockedInteractionsUris$ = combineLatest([
|
||||
this.blockedInteractionsUrisState.state$,
|
||||
this.configService.getFeatureFlag$(FeatureFlag.BlockBrowserInjectionsByDomain),
|
||||
this.configService?.getFeatureFlag$(FeatureFlag.BlockBrowserInjectionsByDomain),
|
||||
]).pipe(
|
||||
map(([blockedUris, blockBrowserInjectionsByDomainEnabled]) => {
|
||||
if (!blockBrowserInjectionsByDomainEnabled) {
|
||||
|
||||
Reference in New Issue
Block a user