From 6dea7504a6105d5d34525e4d85eccf375cd7ef3e Mon Sep 17 00:00:00 2001 From: Mike Amirault Date: Wed, 18 Feb 2026 14:49:51 -0500 Subject: [PATCH] [PM-26732] Remove Chromium ABE importer feature flag (#19039) --- libs/common/src/enums/feature-flag.enum.ts | 2 - .../default-import-metadata.service.ts | 47 +-------- .../services/import-metadata.service.spec.ts | 95 +------------------ 3 files changed, 6 insertions(+), 138 deletions(-) diff --git a/libs/common/src/enums/feature-flag.enum.ts b/libs/common/src/enums/feature-flag.enum.ts index d252f7dcda5..5160e6aa542 100644 --- a/libs/common/src/enums/feature-flag.enum.ts +++ b/libs/common/src/enums/feature-flag.enum.ts @@ -53,7 +53,6 @@ export enum FeatureFlag { /* Tools */ UseSdkPasswordGenerators = "pm-19976-use-sdk-password-generators", - ChromiumImporterWithABE = "pm-25855-chromium-importer-abe", SendUIRefresh = "pm-28175-send-ui-refresh", SendEmailOTP = "pm-19051-send-email-verification", @@ -120,7 +119,6 @@ export const DefaultFeatureFlagValue = { /* Tools */ [FeatureFlag.UseSdkPasswordGenerators]: FALSE, - [FeatureFlag.ChromiumImporterWithABE]: FALSE, [FeatureFlag.SendUIRefresh]: FALSE, [FeatureFlag.SendEmailOTP]: FALSE, diff --git a/libs/importer/src/services/default-import-metadata.service.ts b/libs/importer/src/services/default-import-metadata.service.ts index 393c498e118..a9e767178aa 100644 --- a/libs/importer/src/services/default-import-metadata.service.ts +++ b/libs/importer/src/services/default-import-metadata.service.ts @@ -1,11 +1,9 @@ -import { combineLatest, map, Observable } from "rxjs"; +import { map, Observable } from "rxjs"; -import { ClientType, DeviceType } from "@bitwarden/common/enums"; -import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { SemanticLogger } from "@bitwarden/common/tools/log"; import { SystemServiceProvider } from "@bitwarden/common/tools/providers"; -import { DataLoader, ImporterMetadata, Importers, ImportersMetadata, Loader } from "../metadata"; +import { ImporterMetadata, Importers, ImportersMetadata } from "../metadata"; import { ImportType } from "../models/import-options"; import { availableLoaders } from "../util"; @@ -15,13 +13,8 @@ export class DefaultImportMetadataService implements ImportMetadataServiceAbstra protected importers: ImportersMetadata = Importers; private logger: SemanticLogger; - private chromiumWithABE$: Observable; - constructor(protected system: SystemServiceProvider) { this.logger = system.log({ type: "ImportMetadataService" }); - this.chromiumWithABE$ = this.system.configService.getFeatureFlag$( - FeatureFlag.ChromiumImporterWithABE, - ); } async init(): Promise { @@ -30,13 +23,13 @@ export class DefaultImportMetadataService implements ImportMetadataServiceAbstra metadata$(type$: Observable): Observable { const client = this.system.environment.getClientType(); - const capabilities$ = combineLatest([type$, this.chromiumWithABE$]).pipe( - map(([type, enabled]) => { + const capabilities$ = type$.pipe( + map((type) => { if (!this.importers) { return { type, loaders: [] }; } - const loaders = this.availableLoaders(this.importers, type, client, enabled); + const loaders = availableLoaders(this.importers, type, client); if (!loaders || loaders.length === 0) { return { type, loaders: [] }; @@ -55,34 +48,4 @@ export class DefaultImportMetadataService implements ImportMetadataServiceAbstra return capabilities$; } - - /** Determine the available loaders for the given import type and client, considering feature flags and environments */ - private availableLoaders( - importers: ImportersMetadata, - type: ImportType, - client: ClientType, - withABESupport: boolean, - ): DataLoader[] | undefined { - let loaders = availableLoaders(importers, type, client); - - if (withABESupport) { - return loaders; - } - - // Special handling for Brave and Chrome CSV imports on Windows Desktop - if (type === "bravecsv" || type === "chromecsv") { - try { - const device = this.system.environment.getDevice(); - const isWindowsDesktop = device === DeviceType.WindowsDesktop; - if (isWindowsDesktop) { - // Exclude the Chromium loader if on Windows Desktop without ABE support - loaders = loaders?.filter((loader) => loader !== Loader.chromium); - } - } catch { - loaders = loaders?.filter((loader) => loader !== Loader.chromium); - } - } - - return loaders; - } } diff --git a/libs/importer/src/services/import-metadata.service.spec.ts b/libs/importer/src/services/import-metadata.service.spec.ts index e16965a69f8..d6c0ff64d87 100644 --- a/libs/importer/src/services/import-metadata.service.spec.ts +++ b/libs/importer/src/services/import-metadata.service.spec.ts @@ -1,9 +1,7 @@ import { mock, MockProxy } from "jest-mock-extended"; -import { BehaviorSubject, Subject, firstValueFrom } from "rxjs"; +import { Subject, firstValueFrom } from "rxjs"; import { ClientType } from "@bitwarden/client-type"; -import { DeviceType } from "@bitwarden/common/enums"; -import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { SystemServiceProvider } from "@bitwarden/common/tools/providers"; @@ -17,13 +15,10 @@ describe("ImportMetadataService", () => { let systemServiceProvider: MockProxy; beforeEach(() => { - const configService = mock(); - const environment = mock(); environment.getClientType.mockReturnValue(ClientType.Desktop); systemServiceProvider = mock({ - configService, environment, log: jest.fn().mockReturnValue({ debug: jest.fn() }), }); @@ -34,7 +29,6 @@ describe("ImportMetadataService", () => { describe("metadata$", () => { let typeSubject: Subject; let mockLogger: { debug: jest.Mock }; - let featureFlagSubject: BehaviorSubject; const environment = mock(); environment.getClientType.mockReturnValue(ClientType.Desktop); @@ -42,13 +36,8 @@ describe("ImportMetadataService", () => { beforeEach(() => { typeSubject = new Subject(); mockLogger = { debug: jest.fn() }; - featureFlagSubject = new BehaviorSubject(false); - - const configService = mock(); - configService.getFeatureFlag$.mockReturnValue(featureFlagSubject); systemServiceProvider = mock({ - configService, environment, log: jest.fn().mockReturnValue(mockLogger), }); @@ -78,7 +67,6 @@ describe("ImportMetadataService", () => { afterEach(() => { typeSubject.complete(); - featureFlagSubject.complete(); }); it("should emit metadata when type$ emits", async () => { @@ -129,86 +117,5 @@ describe("ImportMetadataService", () => { "capabilities updated", ); }); - - it("should update when feature flag changes", async () => { - environment.getDevice.mockReturnValue(DeviceType.WindowsDesktop); - const testType: ImportType = "bravecsv"; // Use bravecsv which supports chromium loader - const emissions: ImporterMetadata[] = []; - - const subscription = sut.metadata$(typeSubject).subscribe((metadata) => { - emissions.push(metadata); - }); - - typeSubject.next(testType); - featureFlagSubject.next(true); - - // Wait for emissions - await new Promise((resolve) => setTimeout(resolve, 0)); - - expect(emissions).toHaveLength(2); - // Disable ABE - chromium loader should be excluded - expect(emissions[0].loaders).not.toContain(Loader.chromium); - // Enabled ABE - chromium loader should be included - expect(emissions[1].loaders).toContain(Loader.chromium); - - subscription.unsubscribe(); - }); - - it("should exclude chromium loader when ABE is disabled and on Windows Desktop", async () => { - environment.getDevice.mockReturnValue(DeviceType.WindowsDesktop); - const testType: ImportType = "bravecsv"; // bravecsv supports both file and chromium loaders - featureFlagSubject.next(false); - - const metadataPromise = firstValueFrom(sut.metadata$(typeSubject)); - typeSubject.next(testType); - - const result = await metadataPromise; - - expect(result.loaders).not.toContain(Loader.chromium); - expect(result.loaders).toContain(Loader.file); - }); - - it("should exclude chromium loader when ABE is disabled and getDevice throws error", async () => { - environment.getDevice.mockImplementation(() => { - throw new Error("Device detection failed"); - }); - const testType: ImportType = "bravecsv"; - featureFlagSubject.next(false); - - const metadataPromise = firstValueFrom(sut.metadata$(typeSubject)); - typeSubject.next(testType); - - const result = await metadataPromise; - - expect(result.loaders).not.toContain(Loader.chromium); - expect(result.loaders).toContain(Loader.file); - }); - - it("should include chromium loader when ABE is disabled and not on Windows Desktop", async () => { - environment.getDevice.mockReturnValue(DeviceType.MacOsDesktop); - const testType: ImportType = "bravecsv"; // bravecsv supports both file and chromium loaders - featureFlagSubject.next(false); - - const metadataPromise = firstValueFrom(sut.metadata$(typeSubject)); - typeSubject.next(testType); - - const result = await metadataPromise; - - expect(result.loaders).toContain(Loader.chromium); - expect(result.loaders).toContain(Loader.file); - }); - - it("should include chromium loader when ABE is enabled regardless of device", async () => { - environment.getDevice.mockReturnValue(DeviceType.MacOsDesktop); - const testType: ImportType = "bravecsv"; // bravecsv supports both file and chromium loaders - featureFlagSubject.next(true); - - const metadataPromise = firstValueFrom(sut.metadata$(typeSubject)); - typeSubject.next(testType); - - const result = await metadataPromise; - - expect(result.loaders).toContain(Loader.chromium); - }); }); });